[英]Dynamic Include statements for eager loading in a query - EF 4.3.1
I have this method:我有这个方法:
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();
}
}
I would like to make the list of Includes dynamic.我想使包含动态列表。 I tried:
我试过:
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();
}
}
But it didn't compile.但它没有编译。 I got this error:
我收到此错误:
Cannot implicitly convert type 'System.Data.Entity.Infrastructure.DbQuery' to 'System.Data.Entity.DbSet'.无法将类型“System.Data.Entity.Infrastructure.DbQuery”隐式转换为“System.Data.Entity.DbSet”。 An explicit conversion exists (are you missing a cast?)
存在显式转换(您是否缺少转换?)
Does anyone know how to make the list of Includes dynamic?有谁知道如何使包含动态列表?
Thanks谢谢
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
);
Make the query
variable queryable:使
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();
}
}
Giving the compiler a hint by using IQueryable<CampaignCreative>
instead of var
will work too.通过使用
IQueryable<CampaignCreative>
而不是var
给编译器一个提示也可以。
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.当使用
var
时,编译器推断DbSet<T>
用于query
,它比Include
返回的类型更具体(这是DbQuery<T>
(= DbSet DbSet<T>
T> 的基础 class )实现IQueryable<T>
),所以你可以'不再将结果分配给query
变量。 Hence the compiler error on the query = query.Include(include)
line.因此
query = query.Include(include)
行上的编译器错误。
I wrote this method to retrieve any set of entity dynamically based on their types.我编写此方法是为了根据实体的类型动态检索任何实体集。 I used the
IDbEntity
interface to provide a valid key to search the userId in all the classes.我使用
IDbEntity
接口提供了一个有效的键来搜索所有类中的 userId。 The Util.GetInverseProperties<T>()
method is used to get the properties needed in the Include
statement. Util.GetInverseProperties<T>()
方法用于获取Include
语句中所需的属性。
public IEnumerable<T> GetItems<T>(string userId) where T : class, IDbEntity
{
var query = db.Set<T>().Where(l => l.UserId==userId);
var props = Util.GetInverseProperties<T>();
foreach (var include in props)
query = query.Include(include.Name);
return query
.AsNoTracking()
.ToList();
}
public interface IDbEntity
{
public string UserId { get; set; }
}
public static List<PropertyInfo> GetInverseProperties<T>()
{
return typeof(T)
.GetProperties()
.Where(p => Attribute.IsDefined(p, typeof(InversePropertyAttribute)))
.ToList();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.