繁体   English   中英

Linq:IQueryable扩展方法适用于DBSet但不适用于ICollection

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM