9

我有这样的方法:动态包含在查询预先加载报表 - 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 – 2017-09-11 16:48:14

回答

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 2013-01-24 20:58:08

+0

我不明白。 IQueryable没有包含方法。这不会编译。 – dudeNumber4 2014-03-12 18:00:28

+0

有些项目你会得到这个解决方案的编译错误。使用System.Data.Entity添加;访问IQueryable上的Include扩展方法 – 2014-08-08 04:31:47

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 2013-10-21 12:28:36

+1

我上面说过了,但是我会在这里说出来,以防万一有人错过它:有些项目你会得到这个解决方案的编译错误。使用System.Data.Entity添加;在IQueryable上访问Include扩展方法。 – 2014-08-08 04:32:25

+1

非常好,正是我想要达到的目标。 – Kramer00 2015-12-04 09:21:09