[英]Linq: IQueryable extension methods works on DBSet but not on ICollection
我有一个包含EntityFramework 6.1.0包的项目
我正在使用DB-First模型
通过这种方式扩展了一些模型实体:
public interface IVersionable{
int VersionId{get;set;}
}
public interface IEditable{
bool IsEditable{get;set;}
}
public interface IFullFeatures:IVersionable,IEditable{}
public partial EntityOne:IFullFeatures{
//This is the extension partial class for the auto-generated model class EntityOne that already has interface properties
}
public partial EntityTwo:IFullFeatures{
//This is the extension partial class for the auto-generated model class EntityTwo that already has interface properties
}
自动生成的类EntityOne和EntityTwo具有IFullFeatures所需的所有属性,对于EntityTwo自动生成的文件,我们具有以下ICollection:
public virtual ICollection<EntityOne> EntityOne {get;set;}
最后,我有了扩展方法:
public static class FeaturesExtensionMethod{
public static IQueryable<T> FilterEditable<T>(this IQueryable<T> source) where T:class,IEditable{
return source.Where(s=>s.IsEditable);
}
public static IQueryable<T> FilterVersion<T>(this IQueryable<T> source, int versionId) where T:class,IVersionable{
return source.Where(s=>s.VersionId==versionId);
}
public static IQueryable<T> FullFilter<T>(this IQueryable<T> source, int versionId) where T:class,IVersionable{
return source.FilterEditable().FilterVersion(versionId);
}
}
然后,在运行时,我执行以下命令:
var everyEntitiTwo=ctx.EntityTwo.FullFilter(4).ToList();
没问题,它工作正常并且可以过滤...但是在运行时我改为执行以下命令:
var test= ctx.EntityTwo.Include("EntityOne").Select(et=>et.EntityOne.AsQueryAble().FullFilter(4)).ToList()
我收到此错误:
LINQ to Entities无法识别方法'FullFilter',并且该方法无法转换为商店表达式。
所以问题是:我的扩展方法有什么问题? 为什么在第二种情况下而不是第一种情况下出现此错误?
谢谢。
更新
多亏了乔恩·汉纳(Jon Hanna),我才得以启发这种替代方法来达到相同的结果:
我创建了一个“代理类”来获取过滤器,因为表达式<Func <entityOne,bool>>是强类型的,并且我需要一些更通用的东西:
public static FilterProxies{
public static GetProxiedFilter<T>(int versionId, bool onlyEditable) where T: class, IFullFeatures{
Expression<Func<T,bool>> filteredExp
if(onlyEditable){
filteredExp=(iff=>iff.VersioneId==versionId&&iff.IsEditable);
}
else{
filteredExp=(iff=>iff.VersioneId==versionId);
}
return filteredExp;
}
}
然后,在用法中:
var filter=FilterProxies.GetProxiedFilter<EntityOne>(4,true);
var test= ctx.EntityTwo.Include("EntityOne").Select(et=>et.EntityOne.AsQueryAble().Where(filter)).ToList()
希望对本文有所帮助,感谢乔恩(Jon)启发我应用此解决方案
ctx.EntityTwo.FullFilter(4).ToList();
这立即变成
ctx.EntityTwo.Where(s => s.IsEditable).Where(s => s.VersionId == 4).ToList();
Entity Framework可以处理哪些内容。
var test= ctx.EntityTwo.Include("EntityOne").Select(et=>et.EntityOne.AsQueryAble().FullFilter(4)).ToList()
因为使用您可查询扩展是在查询中 ,并作用于不同类型的可查询的,该方法的调用是传递到实体框架的表达式的一部分,它不知道什么FullFilter()
做,和扼流圈在这一点上。
EF无法将FullFilter方法转换为SQL,因为您正在使用LINQ to Entities。 您可能需要使用Linq to Objects
ctx.EntityTwo.ToList()在您的方法之前,因此它首先获取对象的列表,然后使用该列表执行您的方法,即您正在执行LINQ To Objects
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.