我有这条LINQ代码
private static void Original()
{
using (var context = new AdventureWorksContext())
{
var result =
from product in context.Products
from workorder in product.WorkOrders
select new
{
productName = product.Name,
order = workorder,
};
var result2 =
from item in result
where item.order.WorkOrderRoutings.Count() == 1
select item.productName;
foreach (var item in result2.Take(10))
{
Console.WriteLine(item);
}
}
}
我想打破item.order.WorkOrderRoutings.Count()
部分,并根据某些输入参数替换其他内容,例如item.order.OrderQty
。
我的第一次尝试:
private static Func<WorkOrder, int> GetRoutingCountFunc()
{
return workOrder => workOrder.WorkOrderRoutings.Count();
}
private static void RefactoredFunc()
{
using (var context = new AdventureWorksContext())
{
var result =
from product in context.Products
from workorder in product.WorkOrders
select new
{
productName = product.Name,
order = workorder,
};
var result2 =
from item in result
where GetRoutingCountFunc()(item.order) == 1
select item.productName;
foreach (var item in result2.Take(10))
{
Console.WriteLine(item);
}
}
}
当然没有带有异常的运行时
方法'System.Object DynamicInvoke(System.Object [])'没有支持的SQL转换。
所以我发现我需要加入某种Expression
。我能弄清楚的最合理的是
private static Expression<Func<WorkOrder, int>> GetRoutingCountExpression()
{
return workOrder => workOrder.WorkOrderRoutings.Count();
}
private static void RefactoredExpression()
{
using (var context = new AdventureWorksContext())
{
var result =
from product in context.Products
from workorder in product.WorkOrders
select new
{
productName = product.Name,
order = workorder,
};
var result2 =
from item in result
where GetRoutingCountExpression()(item.order) == 0
select item.productName;
foreach (var item in result2.Take(10))
{
Console.WriteLine(item);
}
}
}
但是这会产生一个编译时错误:where GetRoutingCountExpression()(item.order) == 0
行上的“预期的方法名称”。
如果不是匿名类型,我可以创建一个返回Expression<Func<"anonType", bool>>
的方法,并将其用作where参数。
如何分解LINQ表达式的部分内容?
答案 0 :(得分:1)
最简单的方法是创建转换IQueryable<T>
个实例的方法。例如,像这样的方法:
private static IQueryable<WorkOrder> FilterByRoutingCount(
IQueryable<WorkOrder> orders, int count)
{
return
from workOrder in orders,
where workOrder.WorkOrderRoutings.Count() == count)
select workOrder;
}
您可以像这样使用此方法:
var workorders =
from product in context.Products
from workorder in product.WorkOrders
select workorder;
var result2 =
from workorder in FilterByRoutingCount(workorders, 1)
select workorder.Product.productName;
答案 1 :(得分:0)
您可以这样做:
private static int GetRoutingCount(WorkOrder w)
{
return w.WorkOrderRoutings.Count();
}
如果我们假设item.order
的类型为WorkOrder
,那么您可以像以下一样使用它:
var result2 =
from item in result
where GetRoutingCount(item.order) == 0
select item.productName;
修改强>
这应该做的工作:
Expression<Func<Tuple<string, Order>, bool>> routingCountZero = x =>
x.Item2.Roundings.Count == 0;
你必须使用lambda表达式:
var result2 = result.Where(routingCountZero).Select(x => x.Item1);