编辑:
我正在尝试使用表达式树创建一个查询,以便我可以获得一个简单的结果,但我无法弄清楚它。
我有一些来自EF的实体。 实体PointOfSale,它具有以下属性: 位置(这是地区的孩子) TypeOfClient ImportanceOfPOS QuantityOfSales。
然后我有一个类Filter,它有一个Regions列表,一个TypesOfClients列表,一个Distance of ImportanceOfPOS,以及一个销售数量的最小值和最大值。
课程定义如下:
实体上下文=新实体();
class PointOfSale
{
int p_id;
Location l;
QuantityOfSales q;
TypeOfCliente t;
ImportanceOfClient i;
int l_id_fk;
int t_id_fk;
int i_id_fk;
}
class Location
{
int id;
int region_id_fk;
}
class Region
{
int id;
string value;
}
class ValuesForQuantity
{
int p_id; // ---> Equal to the POS_id
int? min_value;
int? max_value;
}
class QuantityOfSales
{
int id;
int value;
}
class TypeOfCliente
{
int id;
string value;
}
class ImportanceOfClient;
{
int id;
string value;
}
class Filter
{
List<Region> rs;
ValuesForQuantity v;
List<ImportanceOfClient> is;
List<TypeOfClient> ts;
}
请记住,所有字段都是可选字段: 我可能有也可能没有区域,我可能有也可能没有TypeOfClient。此外,在ValueForQuantities中,我可能只选择了一个字段(只是最大值或最小值)。
我正在尝试构建一个动态版本:
var query =
from p in context.PointsOfSale
where p.i exists in filter.is &&
p.t exists in filter.ts &&
p.l in (from l1 in context.Locations where l1 in filter.rs select r) &&
p.t in (from q in context.Quantities where q.value < filter.v.max_value && q.value > filter.v.max_value)
select p;
将生成如下代码:
(p.i.id == filter.i[0] OR p.i.id == filter.i[1] OR p.i.id == filter.i[2])
AND
(p.t.id == filter.t[0] OR p.t.id == filter.t[1])
AND
p.l in (select id from Region r where (r.id == filter.r[0] OR r.id == filter.r[1])
AND
p.q.value < filter.v.max
AND
p.q.value > filter.v.min
到目前为止我的表达树是这样的:
IQueryable<Points_of_sale> queryableDataPOS = context.Points_of_sale.AsQueryable<Points_of_sale>();
ParameterExpression pePOS = Expression.Parameter(typeof(Points_of_sale), "point_of_sale");
ParameterExpression peLocation = Expression.Parameter(typeof(Location), "location");
List<Expression> expressions = new List<Expression>();
if (showRegion)
{
List<Location> ls = getAllLocations(regionList);
List<Expression> choiceExpressions = new List<Expression>();
foreach (Location l in ls)
{
Expression left = Expression.Property(pePOS, typeof(Points_of_sale).GetProperty("location_id_fk"));
left = Expression.Convert(left, t.location_id.GetType());
Expression right = Expression.Constant(t.territory_id);
Expression expression = Expression.Equal(left, right);
choiceExpressions.Add(expression);
}
if (choiceExpressions.Count > 0)
{
Expression totalChoiceExpression = choiceExpressions[0];
for (int i = 1; i < choiceExpressions.Count; i++)
{
totalChoiceExpression = Expression.Or(totalChoiceExpression, choiceExpressions[i]);
}
expressions.Add(totalChoiceExpression);
}
}
if (showTypeOfClient)
{
List<Expression> choiceExpressions = new List<Expression>();
foreach (TypeOfClient choice in clients)
{
Expression left = Expression.Property(pePOS, typeof(Points_of_sale).GetProperty("type_of_client_id_fk"));
left = Expression.Convert(left, choice.type_of_client.GetType());
Expression right = Expression.Constant(choice.type_of_client_id);
Expression expression = Expression.Equal(left, right);
choiceExpressions.Add(expression);
}
if (choiceExpressions.Count > 0)
{
Expression totalChoiceExpression = choiceExpressions[0];
for (int i = 1; i < choiceExpressions.Count; i++)
{
totalChoiceExpression = Expression.Or(totalChoiceExpression, choiceExpressions[i]);
}
expressions.Add(totalChoiceExpression);
}
}
if (showImportanceOfClient)
{
List<Expression> choiceExpressions = new List<Expression>();
foreach (ImportanceOfClient choice in importanceOfClients)
{
Expression left = Expression.Property(pePOS, typeof(Points_of_sale).GetProperty("importance_of_client_id_fk"));
left = Expression.Convert(left, choice.importance_of_client_id.GetType());
Expression right = Expression.Constant(choice.importance_of_client_id);
Expression expression = Expression.Equal(left, right);
choiceExpressions.Add(expression);
}
if (choiceExpressions.Count > 0)
{
Expression totalChoiceExpression = choiceExpressions[0];
for (int i = 1; i < choiceExpressions.Count; i++)
{
totalChoiceExpression = Expression.Or(totalChoiceExpression, choiceExpressions[i]);
}
expressions.Add(totalChoiceExpression);
}
}
if (showQuantityOfSales)
{
// I have no idea how to build this one
}
Expression totalQuery = expressions[0];
// Make the && between all expressions
for (int i = 1; i < expressions.Count; i++)
{
totalQuery = Expression.And(totalQuery, expressions[i]);
}
MethodCallExpression whereCallExpression = Expression.Call(
typeof(Queryable),
"Where",
new Type[] { queryableDataPOS.ElementType },
queryableDataPOS.Expression,
Expression.Lambda<Func<Points_of_sale, bool>>(totalQuery, new ParameterExpression[] { pePOS }));
IQueryable<Points_of_sale> results = queryableDataPOS.Provider.CreateQuery<Points_of_sale>(whereCallExpression);
所以,2个问题:
1 - 如何在没有返回所有位置的方法的情况下构建区域部件。 2 - 如何为Quantity部分创建表达式树分支?
Tnks很多,我希望现在很清楚:)
答案 0 :(得分:1)
首先,从表达式“sub”构建LambdaExpression。然后构建“Contains”调用(实际上它是对Queryable.Any的调用):
var anyExpression = Expression.Call("Queryable.Any", sequence, lambda);
您正在构建此表达式:
Queryable.Any(sequence, x => x > 5);
编辑:看起来您根本不需要构建表达式树。那怎么样:
var query = context.P_List;
if(filter.zs != null && filter.zs.Count != 0)
query = query.Where(p => filter.zs.Contains<int>(p.z));
if(filter.ys != null && filter.ys.Count != 0)
query = query.Where(p => filter.ys.Contains<int>(p.y));
if(filter.as != null && filter.as.Count != 0)
query = query.Where(p => (from ac in context.a_child where filter.as.Contains(ac) select a).Contains(p.a_child));
//and the same for v2...
var list = query.ToList(); //execute the SQL
我希望有效。