Подтвердить что ты не робот

EF 6 фильтрует детские коллекции

Я пытаюсь перенести старый проект из Linq2Sql в EF6, и у меня возникла следующая проблема.

Этот проект является многоязычным (т.е. все тексты имеют более одного перевода), и у меня есть следующая структура db:

Пример таблиц БД

Каков наилучший способ получить все объекты ExampleEntity1 со всеми записями LocalizedContent, отфильтрованными текущим идентификатором языка?

Я могу загрузить все объекты ExampleEntity1 со всеми записями LocalizedContent, используя следующий код: dc.ExampleEntity1.Include(ee => ee.TextEntry.LocalizedContents);

В Linq2Sql я могу фильтровать записи LocalizedContent с помощью loadOptions.AssociateWith, но я не могу найти решение для EF6.

Я видел похожие старые вопросы (размещенные как 2-3 года назад), и мне просто интересно, есть ли решение для EF6. Это очень важная функция для меня, потому что у меня есть десятки объектов в проекте, и я не хочу создавать пользовательские объекты для каждого запроса выбора.

Я также нашел пакет EntityFramework.DynamicFilters nuget, который может помочь с моей проблемой, но я предпочел бы использовать "родную" функциональность EF6, если это возможно..

4b9b3361

Ответ 1

Если вы хотите выполнить фильтрацию в запросе в базе данных, тогда (с EF6) вы должны использовать метод Query

Метод Query обеспечивает доступ к базовому запросу, который будет использоваться Entity Framework при загрузке связанных объектов. Затем вы можете использовать LINQ для применения фильтров к запросу перед выполнением его с вызовом метода расширения LINQ, такого как ToList, Load и т.д.

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(); 
}

Однако очевидным недостатком является то, что вы должны сделать это для каждой записи, и каждый вызов Load выполняет запрос к базе данных.

Если это не будет жестким требованием для вас, я бы выбрал только загрузку всех локализаций и просто фильтрацию в памяти для использования выбранного языка. Я уверен, что производительность не будет проблемой.

Ответ 2

Обратите внимание, что в настоящее время невозможно фильтровать связанные загружаются объекты. Include всегда будет включать все связанные сущности.

Ссылка Msdn

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();   

Вы можете попробовать анонимную проекцию для фильтрации содержимого в включенных сущностях

Команда сообщества Entity работает над этим, вы можете проголосовать здесь

Похожие ответы

Ответ 3

НЕ тестировался И не идеален с точки зрения производительности из-за того, как включить работу... Я бы сделал это вручную, но вот пример того, что вы могли бы сделать.

var result = dc.ExampleEntity1
             .Include(x => x.TextEntry)
             .Include(x => x.TextEntry.LocalizedContents)
             .Include(x => x.TextEntry.LocalizedContents.Local)
             .Where(x => x.id == 'ExampleEntity1Key'
                      && x.TextEntity.LocalContent.Local.Id == 'Value'
              )
             .FirstOrDefault();

Это приведет к тому, что объект ExampleEntity1 будет загружен с полной загрузкой навигации.... где Local сопоставляется с идентификатором.

вы могли бы получить Local как..

var listLocalsForExampleEnitity = result.TextEntry.LocalizedContents.Local.ToList();

или просто вызывать их из того места, где они уже находятся в памяти.

Надеюсь, что это поможет