这是我的方案:我需要使用对链接实体中的属性的“OR”查询从实体中提取数据。
这些是我的实体:
public class Dealer
{
public virtual int id{get;set;}
public virtual string name{get;set;}
public virtual IList<Car> Cars{get;set;}
}
public class Car
{
public virtual int id{get;set;}
public virtual string name{get;set;}
public virtual int kw{get;set;}
}
示例:我想提取所有拥有98kw或100kw汽车的经销商。 Sql示例:
SELECT Dealers.* FROM Dealers INNER JOIN Cars ON Cars.IdDealer = Dealers.Id WHERE Cars.kw = 98 OR Cars.kw = 100
我尝试使用Expression树,但我不知道如何使用它们。 我试过这个:
var dealers = Session.Linq<Dealers>();
ParameterExpression pe = Expression.Parameter(typeof(int), "kw");
Expression tot = null;
var powers = new int[2]{98, 100};
for (var i = 0; i < powers.Length; i++)
{
Expression right = Expression.Constant(int.Parse(powers[i]));
if (i > 0)
tot = Expression.Or(tot, Expression.Equal(pe, right));
else
tot = Expression.Equal(pe, right);
}
dealers = dealers.Where(x => x.Cars.Any(Expression.Lambda<Func<Cars, bool>>(tot, null)));
但是我在尝试执行Expression的最后一行得到了这些编译器错误:
string
类型,因为它不是委托类型System.Collections.Generic.IList<Cars>
不包含Any
的定义和最佳扩展方法重载System.Linq.Enumerable.Any(System.Collections.Generic.IEnumerable,System.Func)有一些无效的参数< / LI>
System.Linq.Expressions.Expression<System.Func<Cars,bool>>
转换为System.Func<Cars,bool>
有什么建议吗?
答案 0 :(得分:2)
根据我留下的评论:
...我可以提出一些建议,可能会或可能不会受到欢迎。在我看来,你应该避免在开放环境中以这种方式使用RAW表达式。我衷心地建议你采用一种更封闭的方法,看看像albahari谓词建构者这样的东西:albahari.com/nutshell/predicatebuilder.aspx会为你节省很多挫折感。页面上也有一些很好的工作示例
我无法强调这给我们承担的许多项目带来的好处。此库/方法的用法转换为以下行的表达式:
IQueryable<Product> SearchProducts (params string[] keywords)
{
var predicate = PredicateBuilder.False<Product>();
foreach (string keyword in keywords)
{
string temp = keyword;
predicate = predicate.Or (p => p.Description.Contains (temp));
}
return dataContext.Products.Where (predicate);
}
等。因此,您可以构建相当复杂的语句将所有内部隐藏起来。这是完全合理的,特别是如果您现在或将来可能有更多的初级开发人员处理代码。我强烈建议你放纵自己的好奇心,徘徊在链接上,从那里获得更好的感受。
答案 1 :(得分:1)
尝试像这样更改你的代码
var dealers = Session.Linq<Dealers>();
ParameterExpression pe = Expression.Parameter(typeof(Car), "c");
var kw = Expression.Property(pe, "kw");
var powers = new string[2]{"98", "100"};
Expression tot = powers.Select(p=>Expression.Constant(int.Parse(p)))
.Select(p=>Expression.Equal(kw,p))
.Aggregate((a,b)=>Expresion.Or(a,b));
您还需要将Cars
声明更改为IEnumerable<Car>
或IQueriable<Car>
如果 IEnumerable<Car>
,则将其称为
dealers = dealers.Where(x => x.Cars.Any(Expression.Lambda<Func<Cars, bool>>(tot, pe).Compile()));
如果 IQueriable<Car>
,则将其称为
dealers = dealers.Where(x => x.Cars.Any(Expression.Lambda<Func<Cars, bool>>(tot, pe)));
答案 2 :(得分:0)
将Expression.Lambda的结果转换为
Expression<Func<Car, bool>>
你需要传递参数表达式:
x.Cars.Any( ( Expression<Func<Car, bool>> )Expression.Lambda<Func<Cars, bool>>( tot, pe ) )