9

у меня есть этот метод:Dynamic Включают заявления для нетерпеливой загрузки в запросе - EF 4.3.1

public CampaignCreative GetCampaignCreativeById(int id) 
     { 
      using (var db = GetContext()) 
      { 
       return db.CampaignCreatives 
        .Include("Placement") 
        .Include("CreativeType")      
        .Include("Campaign") 
        .Include("Campaign.Handshake") 
        .Include("Campaign.Handshake.Agency") 
        .Include("Campaign.Product") 
        .AsNoTracking() 
        .Where(x => x.Id.Equals(id)).FirstOrDefault(); 
      } 
     } 

Я хотел бы сделать список включает в себя динамический. Я пробовал:

public CampaignCreative GetCampaignCreativeById(int id, string[] includes) 
     { 
      using (var db = GetContext()) 
      { 
       var query = db.CampaignCreatives; 

       foreach (string include in includes) 
       { 
        query = query.Include(include); 
       } 

       return query.AsNoTracking() 
        .Where(x => x.Id.Equals(id)).FirstOrDefault();      
      } 
     } 

Но он не скомпилировался. Я получил эту ошибку:

Невозможно неявно преобразовать тип 'System.Data.Entity.Infrastructure.DbQuery' в 'System.Data.Entity.DbSet'. Явное преобразование существует (вы отсутствуете в лите?)

Кто-нибудь знает, как сделать список включений динамическим?

Благодаря

+0

Я сделал плагин, который делает именно это, вот ссылка https://www.codeproject.com/Tips/1205294/Entity-Framework-Dynamic-Include-Hier archy –

ответ

9

Сделать query переменные запрашиваемое:

public CampaignCreative GetCampaignCreativeById(int id, string[] includes) 
{ 
    using (var db = GetContext()) 
    { 
     var query = db.CampaignCreatives.AsQueryable(); 
     foreach (string include in includes) 
     { 
      query = query.Include(include); 
     } 

     return query 
      .AsNoTracking() 
      .Where(x => x.Id.Equals(id)) 
      .FirstOrDefault();      
    } 
} 
+0

Какая версия EntityFramework требует этого? – cmour

+0

Я не понимаю. IQueryable не имеет метода Include. Это не компилируется. – dudeNumber4

+0

В некоторых проектах вы получите ошибку компиляции с этим решением. Добавить с помощью System.Data.Entity; для доступа к методу расширения Include в IQueryable –

1

Давать компилятор подсказку, используя IQueryable<CampaignCreative> вместо var тоже будет работать.

IQueryable<CampaignCreative> query = db.CampaignCreatives; 
// or 
DbQuery<CampaignCreative> query = db.CampaignCreatives; 

При использовании var компилятор выводит DbSet<T> для query, который является более точным, чем тип возвращаемого Include (который является DbQuery<T> (= базовый класс DbSet<T>) реализации IQueryable<T>), так что вы не можете присвоить результат переменная query. Следовательно, ошибка компилятора на линии query = query.Include(include).

24

Я больше люблю нестрочный выразительный способ определения. Главным образом потому, что он не полагается на магические строки.

Для примера кода, это будет выглядеть примерно так:

public CampaignCreative GetCampaignCreativeById(int id) { 
    using (var db = GetContext()) { 
     return db.CampaignCreatives 
      .Include(cc => cc.Placement) 
      .Include(cc => cc.CreativeType)      
      .Include(cc => cc.Campaign.Select(c => 
       c.Handshake.Select(h => h.Agency))) 
      .Include(cc => cc.Campaign.Select(c => c.Product) 
      .AsNoTracking() 
      .Where(x => x.Id.Equals(id)) 
      .FirstOrDefault(); 
    } 
} 

А чтобы те, динамична, это то, как вы делаете это:

public CampaignCreative GetCampaignCreativeById(
    int id, 
    params Expression<Func<T, object>>[] includes 
) { 
    using (var db = GetContext()) { 
     var query = db.CampaignCreatives; 
     return includes 
      .Aggregate(
       query.AsQueryable(), 
       (current, include) => current.Include(include) 
      ) 
      .FirstOrDefault(e => e.Id == id); 
    } 
} 

Который используется так:

var c = dataService.GetCampaignCreativeById(
    1, 
    cc => cc.Placement, 
    cc => cc.CreativeType, 
    cc => cc.Campaign.Select(c => c.Handshake.Select(h => h.Agency)), 
    cc => cc.Campaign.Select(c => c.Product 
); 
+0

Это действительно хорошо! – pomeroy

+1

Я сказал это выше, но я скажу это здесь, если кто-то пропустил это: в некоторых проектах вы получите ошибку компиляции с этим решением. Добавить с помощью System.Data.Entity; для доступа к методу расширения Include в IQueryable. –

+1

очень приятно, именно то, что я пытался добиться. – Kramer00