C# 如何仅当应用过滤器时存在结果时才在LINQ to SQL表达式中应用过滤器?
我有一个函数想转换成LINQ到SQL表达式,但我不知道如何转换。从LINQ查询中调用此函数,对结果集中的每一行调用一次。传入的productAreaId可能引用有效数据,也可能引用无效数据,因此我必须进行检查,如果应用筛选器后存在任何行,则仅按productAreaId进行筛选: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
//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()
};