我需要编写一个相当复杂的查询。我希望尽可能使用Linq to Sql。数据库是这样的:
客户(第一,最后,身份证,性别)
订单(日期,数量,重量,物品名称,价格)
地址(城市,州,邮编)
查询将允许用户通过任何这些字段进行搜索,并且在数字字段的情况下,搜索<,=或>他们想要的。
这样的东西就是我需要实现的示例查询:
查询1: 选择名字='John'并且至少有一个订单的客户(重量> 40或数量> 10或价格> 5)和zipcode = 12345。
查询2: 选择名字='John'的客户,并且至少有一个订单的权重< 20和ItemName ='widget'和Quantity = 10)和zipcode = 12345。
我可以获得搜索客户的基本部分,但我仍然坚持搜索订单表,用户可以在其中以OR方式指定<> =。
query = Context.Customers.AsQueryable();
if (searchingFirstName) query = query.Where(cust => cust.First == firstName);
if (searchingLastName) query = query.Where(cust => cust.Last == lastName);
if (searchingZip) query = query.Where(cust => cust.Address.Zip == zip);
// using dynamic Linq
if (searchingGender) query = query.Where("Gender == @0", gender);
// how do I search the Orders? The dynamic linq functions appear
// to only work on the top level table
答案 0 :(得分:1)
您可以使用LinqKit中的PredicateBuilder。它添加了一些新的扩展方法来预测lambdas:
var predicate = PredicateBuilder.True<Customer>();
if (searchingFirstName)
{
predicate = predicate.And(cust => cust.First == firstName);
}
if (searchingOrders)
{
// Some code to unify the .And() and .Or() cases
Expression<Func<Order, bool>> subpredicate;
Func<Expression<Func<Order, bool>>, Expression<Func<Order, bool>>, Expression<Func<Order, bool>>> joiner;
if (orderMethodAny)
{
subpredicate = PredicateBuilder.True<Order>();
joiner = PredicateBuilder.And;
}
else
{
subpredicate = PredicateBuilder.False<Order>();
joiner = PredicateBuilder.Or;
}
if (searchingOrderDate)
{
// ...
}
if (searchingOrderWeight)
{
switch (orderOp)
{
case Op.Less:
subpredicate = joiner(subpredicate, ord => ord.Weight < orderWeight);
break;
case Op.LessEqual:
subpredicate = joiner(subpredicate, ord => ord.Weight <= orderWeight);
break;
case Op.Equal:
subpredicate = joiner(subpredicate, ord => ord.Weight == orderWeight);
break;
case Op.GreaterEqual:
subpredicate = joiner(subpredicate, ord => ord.Weight >= orderWeight);
break;
case Op.Greater:
subpredicate = joiner(subpredicate, ord => ord.Weight > orderWeight);
break;
case Op.NotEqual:
subpredicate = joiner(subpredicate, ord => ord.Weight != orderWeight);
break;
}
}
if (searchingOrderQuantity)
{
// ...
}
if (searchingOrderItemName)
{
// ...
}
if (searchingOrderPrice)
{
// ...
}
predicate = predicate.And(cust => cust.Orders.Any(subpredicate));
}
if (searchingZipCode)
{
predicate = predicate.And(cust => cust.ZipCode == zipCode);
}
var query = Context.Customers.Where(predicate);
如果您使用实体框架,则可能需要在谓词上调用.Expand()
,然后在可查询项上调用.AsExpandable()
。