Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF 6 filtering child collections

I'm trying to migrate old project from Linq2Sql to EF6 and I got following issue.

This project is multilingual (i.e. all texts have more than 1 translation) and I have following db structure:

Example of DB tables

What is the best way to get all ExampleEntity1 objects with all LocalizedContent records filtered by current language id?

I can load all ExampleEntity1 objects with all LocalizedContent records using following code: dc.ExampleEntity1.Include(ee => ee.TextEntry.LocalizedContents);

In Linq2Sql I can filter LocalizedContent records using loadOptions.AssociateWithbut I can't find any solution for EF6.

I saw similar old questions (posted like 2-3 years ago) and I'm just wondering if there is a solution for EF6. It is a very critical feature for me because I have dozens of entities in the project and I don't want to create custom objects for each select query.

I also found EntityFramework.DynamicFilters nuget package which can help with my issue, but I would prefer to use "native" EF6 functionality if possible..

like image 252
Mike Avatar asked Dec 04 '15 01:12

Mike


2 Answers

Note that it is not currently possible to filter which related entities are loaded. Include will always bring in all related entities.

Msdn Reference

var result = dc.ExampleEntity1.Include(ee =>ee.TextEntry.LocalizedContents)
               .Select(x=>new
               {
                  //Try anonymous or a projection to your model.
                  //As this Select is IQuerable Extension it will execute in the data store and only retrieve filtered data.
                  exampleEntity = x,
                  localizedContetnt = x.TextEntry.LocalizedContents.Where(g=>g.Id==YourKey),
               }).FirstOrDefault();   

You could try anonymous projection to filter contents in the Included entities

Entity framework team is working on this you could cast your vote here

Similar Answer

like image 135
Eldho Avatar answered Nov 07 '22 23:11

Eldho


If you want to perform the filtering in the query to the database then (as of EF6) you have to use the Query method:

The Query method provides access to the underlying query that the Entity Framework will use when loading related entities. You can then use LINQ to apply filters to the query before executing it with a call to a LINQ extension method such as ToList, Load, etc.

using (var context = new BloggingContext()) 
{ 
  var blog = context.Blogs.Find(1); 

  // Load the posts with the 'entity-framework' tag related to a given blog 
  context.Entry(blog) 
    .Collection(b => b.Posts) 
    .Query() 
    .Where(p => p.Tags.Contains("entity-framework") 
    .Load(); 

   // Load the posts with the 'entity-framework' tag related to a given blog  
   // using a string to specify the relationship  
   context.Entry(blog) 
     .Collection("Posts") 
     .Query() 
     .Where(p => p.Tags.Contains("entity-framework") 
     .Load(); 
}

However, the obvious drawback is that you have to do this per entry and each Load call executes a query against the database.

Unless it's a hard requisite for you I would opt for just loading all the localizations and simply filter in memory to use the selected language one. I'm pretty sure the performance won't be an issue.

like image 40
jnovo Avatar answered Nov 07 '22 21:11

jnovo