C# 如何仅当应用过滤器时存在结果时才在LINQ to SQL表达式中应用过滤器?

C# 如何仅当应用过滤器时存在结果时才在LINQ to SQL表达式中应用过滤器?,c#,linq,linq-to-sql,expression-trees,C#,Linq,Linq To Sql,Expression Trees,我有一个函数想转换成LINQ到SQL表达式,但我不知道如何转换。从LINQ查询中调用此函数,对结果集中的每一行调用一次。传入的productAreaId可能引用有效数据,也可能引用无效数据,因此我必须进行检查,如果应用筛选器后存在任何行,则仅按productAreaId进行筛选: //Forgive the contrived example... public static IQueryable<Order> GetOrders(int orderNumber, int? prod

我有一个函数想转换成LINQ到SQL表达式,但我不知道如何转换。从LINQ查询中调用此函数,对结果集中的每一行调用一次。传入的productAreaId可能引用有效数据,也可能引用无效数据,因此我必须进行检查,如果应用筛选器后存在任何行,则仅按productAreaId进行筛选:

//Forgive the contrived example...
public static IQueryable<Order> GetOrders(int orderNumber, int? productAreaId, 
    OSDataContext db)
{
    var orders = db.Orders.Where(o => o.OrderNumber == orderNumber &&
        o.Group.GroupTypeId != (int)GroupTypeId.INTERNAL &&
        !o.Deleted);

    if (productAreaId != null)
    {
        var orders2 = orders.Where(o => o.ProductAreaId == productAreaId);
        if (orders2.Any()) return orders2;
    }
    return orders;
}
还值得注意的是,订单和客户位于数据库服务器上的两个不同数据库中,但它们都来自相同的DataContext

public static IQueryable<Order> GetOrders(int orderNumber, int? productAreaId, OSDataContext db)
{
    var orders = db.Orders.Where(o => o.OrderNumber == orderNumber &&
        o.Group.GroupTypeId != (int)GroupTypeId.INTERNAL &&
        !o.Deleted);


    if (productAreaId != null)
    {
        var orders2 = orders.Where(o => o.ProductAreaId == productAreaId);
return orders2.Select(x => new {x, Type = 2 }).Concat(orders.Select(x => new {x, Type = 1 })).OrderBy(x => x.Type);
    }
    return orders;
}

以将查询限制为最高优先级顺序。这将具有次优性能。

对于原始方法,这可能会更好:

public static IQueryable<Order> GetOrders(int orderNumber, int? productAreaId, 
    OSDataContext db)
{
    var orders = db.Orders.Where(o => o.OrderNumber == orderNumber &&
        o.Group.GroupTypeId != (int)GroupTypeId.INTERNAL &&
        !o.Deleted);
    if(productAreaId != null)
    {
        orders = orders.Where(
            o => !orders.Any(o2 => o2.ProductAreaId == productAreaId) ||
                    o.ProductAreaId == productAreaId);
    }
    return orders;
}

也许是这样的:

var customerData = 
    from c in db.Customers
    let orders = db.Orders.Where(o => o.OrderNumber == c.orderNumber &&
        o.Group.GroupTypeId != (int)GroupTypeId.INTERNAL &&
        !o.Deleted)
    let orders2 = orders.Where(o => o.ProductAreaId == c.productAreaId)
    select new 
    {
        id = c.Id,
        name = c.Name,
        lastOrder = c.productAreaId != null && orders2.Any() ?
            orders2.FirstOrDefault() :
            orders.FirstOrDefault() 
    };

所以你是说,即使指定了产品区域,如果应用过滤器后没有匹配的订单,你也不想应用过滤器?@StriplingWarrior:是的,没错。我真的想摆脱这种方法。函数需要返回表达式,而不是IQueryable。如果我返回一个IQueryable,则该函数不能组合成一个更大的查询。@Roy Tinker:请提供有关如何调用该函数的详细信息,以便我了解您可能有哪些选项。顺便说一句,对原始方法的建议很好。。。只是不是我现在想要的:——|我正试图摆脱这种方法。该函数需要返回一个表达式,以便可以将其组合到更大的查询中。也许我应该发布更大的问题,让问题更清楚。谢谢,这为我指明了正确的方向。let关键字太棒了!
GetOrders().Where(x => x.Type == GetOrders().Max(x => x.Type))
public static IQueryable<Order> GetOrders(int orderNumber, int? productAreaId, 
    OSDataContext db)
{
    var orders = db.Orders.Where(o => o.OrderNumber == orderNumber &&
        o.Group.GroupTypeId != (int)GroupTypeId.INTERNAL &&
        !o.Deleted);
    if(productAreaId != null)
    {
        orders = orders.Where(
            o => !orders.Any(o2 => o2.ProductAreaId == productAreaId) ||
                    o.ProductAreaId == productAreaId);
    }
    return orders;
}
var customerData = 
    from c in db.Customers
    let productAreaId = c.PreferredProductAreaId
    let orders = 
        db.Orders
        .Where(o => o.OrderNumber == c.LastOrderNumber &&
            o.Group.GroupTypeId != (int)GroupTypeId.INTERNAL &&
            !o.Deleted)
        .OrderBy(o => o.Date)
    let lastOrderInProductArea = productAreaId != null
        ? orders.FirstOrDefault(o => o.ProductAreaId == productAreaId)
        : null
    select new 
    {
        id = c.Id,
        name = c.Name,
        lastOrder = lastOrderInProductArea != null
            ? lastOrderInProductArea
            : orders.FirstOrDefault()
    };
var customerData = 
    from c in db.Customers
    let orders = db.Orders.Where(o => o.OrderNumber == c.orderNumber &&
        o.Group.GroupTypeId != (int)GroupTypeId.INTERNAL &&
        !o.Deleted)
    let orders2 = orders.Where(o => o.ProductAreaId == c.productAreaId)
    select new 
    {
        id = c.Id,
        name = c.Name,
        lastOrder = c.productAreaId != null && orders2.Any() ?
            orders2.FirstOrDefault() :
            orders.FirstOrDefault() 
    };