I need to return a set of MyClass
based on a tuple value list. This tuple values are used to get the correct object from database.
In order to avoid calling db many times, I'm trying to use a Union
to build the query and then get all the data from db only once calling .ToList()
method.
In this case, if there are no results in the query I need to return a default value object. When I apply the DefaultIfEmpty
method I get an error. The idea is if I receive a List
of 15 tuples, I need to return 15 results, if there were no results, they should be populated with the built default Class
value.
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;
}
Any idea of how to accomplish this in an optimized way?
Perhaps you can remove DefaultIfEmpty and add the missing MyClasses later.
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);