C# LINQ to实体不支持调用
我在LINQ to实体中有以下查询:C# LINQ to实体不支持调用,c#,linq-to-entities,C#,Linq To Entities,我在LINQ to实体中有以下查询: var query = from p in db.Products where p.Price > 10M select p; 此时查询尚未执行,我想编写一个查询,根据某些条件返回true/false: return query.Any(p => p.IsInStock && (p.Category == "Beverage" ||
var query = from p in db.Products
where p.Price > 10M
select p;
此时查询尚未执行,我想编写一个查询,根据某些条件返回true/false:
return query.Any(p => p.IsInStock &&
(p.Category == "Beverage" ||
p.Category == "Other"));
这很好用;然而,我想从我的代码中得到一些重用。我有许多方法需要根据类别是饮料还是其他进行过滤,因此我尝试创建一个代理:
Func<Product, bool> eligibleForDiscount = (product) => product.Category == "Beverage" || product.Category == "Other";
return query.Any(p => p.IsInStock && eligibleForDiscount(p));
这给了我一个错误,即LINQtoEntities不支持调用。为什么我不能用内联代码代替这样的委托,有没有其他方法可以实现重用?回想一下,在后台
Linq to-{DATABASE}
只是将您生成的IQueryable
转换为Sql
您不能这样内联代码,因为调用
(当您调用函数
或操作
时实际调用的方法)没有一致的方法将其转换为sql语句(您可以在其中执行任何操作)
也就是说,您可以通过拆分来重用零件:
var query = from p in db.Products
where p.Price > 10M
select p;
query = query.Where(p => p.IsInStock);
query = query.Where(p => p.Category == "Beverage" || p.Category == "Other");
return query.Any();
这两种方法都可以放入方法中,这些方法接受
IQueryable
,并返回相同的结果(但经过过滤)。然后你可以随心所欲地重复使用 问题在于,IQueryable
需要生成一个SQL表达式来传递给RDBMS,而当它只有一个不透明的谓词时,它就不能这样做
显而易见但效率低下的方法是按如下方式重写查询:
return query.Where(p => p.IsInStock).AsEnumerable().Any(eligibleForDiscount);
bool GotEligible(Expression<Func<Product,bool>> pred) {
return query.Where(p => p.IsInStock).Any(pred);
}
一个不那么琐碎的方法如下:
return query.Where(p => p.IsInStock).AsEnumerable().Any(eligibleForDiscount);
bool GotEligible(Expression<Func<Product,bool>> pred) {
return query.Where(p => p.IsInStock).Any(pred);
}
bool-gotQualified(表达式pred){
返回query.Where(p=>p.IsInStock).Any(pred);
}
请注意,此方法如何使用谓词表达式而不是谓词。现在它对EF是透明的,可以毫无问题地转换为SQL查询。只要您坚持使用IQueryable,就可以在函数中保留可重用的查询
public IQueryable<Product> EligibleForDiscount(IQueryable<Product> products)
{
return products.Where(p => product.Category == "Beverage" ||
product.Category == "Other");
}
public IQueryable deligiblefordiscount(IQueryable产品)
{
退货产品。其中(p=>product.Category==“饮料”|
产品类别=“其他”);
}
现在像调用任何其他函数一样调用它:
IQueryable<Product> query = (from p in db.Products
where p.Price > 10M
select p);
query = EligibleForDiscount(query);
IQueryable查询=(来自db.Products中的p
其中p.价格>10M
选择p);
query=EligibleForDiscount(查询);
考虑到这个问题没有一个被接受的答案,我不知道这个PredicateBuilder是什么,我不认为这个问题是重复的。所以你的建议是有一个方法,它可以IQueRead并且返回IQueRead而不是一个委托。我猜它们做的事情是一样的:)它们做的事情完全一样,而且它的可重用性更高……采用IQueryable和返回IQueryable的方法和函数真的很强大。作为额外的好处,这也可以被做成一个扩展方法,提供定制的光滑查询。WhereIsAnyCategory(“饮料”、“其他”)(或query.WhereBeverageOrOther())在IQueryable接口上键入语法。顺便说一句,您想去掉任何
条款中的(p)
,可能您的意思是gotQualified
;)