Dynamic Include statements for eager loading in a query - EF 4.3.1

戏子无情 提交于 2019-11-28 09:16:04

Make the query variable queryable:

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

I am more fond of the non-string expressive way of defining includes. Mainly because it doesn't rely on magic strings.

For the example code, it would look something like this:

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

And to make those dynamic, this is how you do that:

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

Which is used like this:

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

Giving the compiler a hint by using IQueryable<CampaignCreative> instead of var will work too.

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

When using var the compiler infers DbSet<T> for query which is more specific than the type returned by Include (which is DbQuery<T> (=base class of DbSet<T>) implementing IQueryable<T>), so you can't assign the result to the query variable anymore. Hence the compiler error on the query = query.Include(include) line.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!