Используйте DefaultIfEmpty, чтобы получить значения класса по умолчанию при использовании Union
Мне нужно вернуть набор MyClass
на основе списка значений кортежа. Эти значения кортежа используются для получения правильного объекта из базы данных. Чтобы не вызывать дБ много раз, я пытаюсь использовать Union
построить запрос, а затем получить все данные из базы данных только один раз, вызывая .ToList()
метод. В этом случае, если в запросе нет результатов, мне нужно вернуть объект значения по умолчанию. Когда я применяю DefaultIfEmpty
метод я получаю ошибку. Идея в том, если я получу List
из 15 кортежей мне нужно вернуть 15 результатов, если результатов не было, они должны быть заполнены встроенным значением по умолчанию Class
значение.
public ISet<MyClass> Post([FromBody] IList<Tuple<string, string>> codesToFilter)
{
IEnumerable<MyClass> filteredObjectsByCodes = new List<MyClass>();
foreach (Tuple<string, string> tupleElement in codesToFilter)
{
//Class built based on parameters to be returned if there are no records in db
MyClass classDefaultValue = new MyClass(tupleElement.Item1,
"A default property string",
"Default text",
tupleElement.Item2);
var filteredObjects = (from entity in DatabaseContext.MyEntities
where (entity.Property1 == tupleElement.Item1 &&
entity.Property4== tupleElement.Item2)
select new MyClass
(
entity.Property1,
entity.Property2,
entity.Property3,
entity.Property4
)
).DefaultIfEmpty(classDefaultValue);
filteredObjectsByCodes = filteredObjectsByCodes.Union(filteredObjects);
}
var filteredObjectsResult = new HashSet<MyClass>((filteredObjectsByCodes.ToList()));
return filteredObjectsResult;
}
Любая идея о том, как сделать это оптимизированным способом?
2 ответа
Возможно, вы можете удалить DefaultIfEmpty и добавить недостающие MyClasses позже.
IEnumerable<MyClass> results = filteredObjectsByCodes.ToList();
var missing = codesToFilter
.Where(c => results.All(f => f.Property1 != c.Item1 && f.Property4 != c.Item2))
.Select(c => new MyClass(tupleElement.Item1.. );
results = results.Union(missing);
return new HashSet<MyClass>(results);
Вызов AsEnumerable
до звонка DefaultIfEmpty
, Это операция, которую просто не имеет смысла выполнять в конце БД. Получите результаты из базы данных, и если она пуста, дайте приложению добавить элемент по умолчанию в последовательность.
Чтобы избежать выполнения Union
на стороне приложения все, что вам нужно сделать, это применить AsEnumerable().DefaultIfEmpty(...)
звоните после объединения различных запросов к БД. Там нет необходимости для DefaultIfEmpty
выполняется перед агрегированием всех подзапросов.