C# 使用动态linq to sql查询子表?

C# 使用动态linq to sql查询子表?,c#,.net,linq-to-sql,C#,.net,Linq To Sql,我需要编写一个相当复杂的查询。如果可能的话,我希望使用LINQtoSQL来实现这一点。数据库如下所示: 客户(第一位、最后一位、ID、性别) 订单(日期、数量、重量、项目名称、价格) 地址(城市、州、邮编) 查询将允许用户通过这些字段中的任何一个进行搜索,如果是数字字段,则允许用户根据需要进行搜索 类似的内容是我需要实现的示例查询: 问题1: 选择名为“John”且至少有一个订单(重量>40或数量>10或价格>5)且zipcode=12345的客户 问题2: 选择名为“John”且至少有一个

我需要编写一个相当复杂的查询。如果可能的话,我希望使用LINQtoSQL来实现这一点。数据库如下所示:

客户(第一位、最后一位、ID、性别)
订单(日期、数量、重量、项目名称、价格)
地址(城市、州、邮编)

查询将允许用户通过这些字段中的任何一个进行搜索,如果是数字字段,则允许用户根据需要进行搜索

类似的内容是我需要实现的示例查询:

问题1: 选择名为“John”且至少有一个订单(重量>40或数量>10或价格>5)且zipcode=12345的客户

问题2: 选择名为“John”且至少有一个订单(重量<20,项目名为“widget”且数量=10)且zipcode=12345的客户

我可以获得搜索客户的基本部分,但我一直停留在搜索订单表上,用户可以在其中以OR方式指定=


您可以从中使用PredicateBuilder。它添加了一些新的扩展方法来谓词lambda:

var predicate=PredicateBuilder.True();
如果(搜索名字)
{
谓词=谓词和(cust=>cust.First==firstName);
}
如果(搜索订单)
{
//一些用于统一.And()和.Or()案例的代码
表达子预测;
Func joiner;
if(orderMethodAny)
{
subpredicate=PredicateBuilder.True();
joiner=PredicateBuilder.And;
}
其他的
{
subpredicate=PredicateBuilder.False();
joiner=谓词生成器。或;
}
如果(搜索或指定日期)
{
// ...
}
如果(搜索或重量)
{
交换机(orderOp)
{
案例Op.Less:
次级信贷=联合国(次级信贷,订单=>订单重量<订单重量);
打破
案例Op.LessEqual:
次级信贷=联合国(次级信贷,ord=>ord.WERGET ord.WERGET==订单重量);
打破
案例Op.GreaterEqual:
次级信贷=联合国(次级信贷,订单=>订单重量>=订单重量);
打破
案例Op.更大:
次级信贷=联合国(次级信贷,订单=>订单重量>订单重量);
打破
案例Op.NotEqual:
次级信用卡=接合者(次级信用卡,订单=>订单重量!=订单重量);
打破
}
}
如果(搜索订单数量)
{
// ... 
}
如果(搜索OrderItemName)
{
// ...
}
如果(搜索或定价)
{
// ...
}
谓词=谓词和(cust=>cust.Orders.Any(subpredicate));
}
如果(搜索ZipCode)
{
谓词=谓词和(cust=>cust.ZipCode==ZipCode);
}
var query=Context.Customers.Where(谓词);

在将谓词作为参数传递之前,您可能需要在谓词上调用
.Expand()
,如果您使用的是实体框架,则可能需要在查询表上调用
.AsExpandable()

非常感谢。回答得很好。我必须在子预测上调用.Compile()。predicate=predicate.And(cust=>cust.Orders.Any(subpredicate.Compile());不幸的是,我现在意识到我的问题并不完全正确..Compile()将表达式转换为委托。这将使系统在客户端而不是数据库上进行筛选。在重新编写以使用真正的查询后,我不再需要任何Expand()、AsExpandable()或Compile()。但它工作得很好。

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
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);