I have this piece of LINQ code
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);
}
}
}
I want to break out the item.order.WorkOrderRoutings.Count() part and replace with something else, like item.order.OrderQty based on some input parameter.
My first attempt:
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);
}
}
}
of course fails a runtime with an exception
Method ‘System.Object DynamicInvoke(System.Object[])’ has no supported translation to SQL.
So I figured out I need to put in some kind of Expression. The most reasonable I can figure out is
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);
}
}
}
But that gives a compile time error: “Method name expected” on the line where GetRoutingCountExpression()(item.order) == 0.
If it wasn’t for the anonymous type I could have created a method returning Expression<Func<"anonType", bool>> and use that as the where argument.
How do I break out parts of the LINQ-expression?
The easiest thing to do is to create methods that transform
IQueryable<T>instances. For instance a method like this:You can use this method like this: