Разбейте части выражения LINQ2SQL - PullRequest
1 голос
/ 21 сентября 2011

У меня есть этот фрагмент кода 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?

Ответы [ 2 ]

1 голос
/ 21 сентября 2011

Самое простое, что нужно сделать - это создать методы, которые преобразуют 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;
0 голосов
/ 22 сентября 2011

Вы можете просто сделать как:

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;

Вам придется использовать лямбда-выражения:

var result2 = result.Where(routingCountZero).Select(x => x.Item1);
...