IQueryable上的扩展没有转换为SQL

时间:2012-11-16 13:42:58

标签: sql linq iqueryable

我现在已经整整摆弄了两天,现在出现了一个简单的问题。

我有一个包含Product实体和ProductLocationHistory实体的数据库。 ProductLocationHistory引用了仓库,联系人或关系。每次移动产品时,它都会获得一个新条目,以便跟踪产品的过去。因此,当前位置是由ProductLocationHistory的DateCreation字段确定的最后一个条目。

一个例子:

var storehousesWithBorrowedItems = productService.GetAllProducts()
    .Select(p => p.ProductLocationHistories
        .SingleOrDefault(plh => plh.DateCreation == p.ProductLocationHistories.Max(grp => grp.DateCreation)))
    .Select(plh => plh.Storehouse)
    .Distinct();

这些都是目前有产品的仓库。

当然,在我需要确定产品的当前位置时,在代码中写出来是非常不方便的。由于可能存在一致性问题,我认为对Product中当前ProductLocationHistory的引用完全不受欢迎。我更喜欢这样的东西:

Product.ProductLocationHistories.Current();

所以我试过了:

public static ProductLocationHistory Current(this EntitySet<ProductLocationHistory> plhs)
    {
        return plhs.SingleOrDefault(plh => plh.DateCreation == plhs.Max(grp => grp.DateCreation));
    }

这对查询不起作用,因为我得到'当前没有支持翻译到sql',因为Product和ProductLocationHistory的组合通常是查询的'开始'我想保持IQueryable而不是立即到IEnumerable和查询每个产品以确定当前位置!更不用说之后的其他内容......经常使用任何实体的当前日志条目,只要它工作并保持可查询性,.Current()函数的复杂程度就没那么重要了。我希望我的.Current(...)函数可以工作,因为底层代码是可查询的,但我仍然得到一个例外。当代码是第一个示例中的内联时,我没有得到异常。

我经历过Func,ProductLocationHistory&gt;&gt;等可能性。并且还使用表达式&lt; ...&gt;围绕它,但我找不到我正在寻找的例子。 Product.CurrentProductLocationHistory()类型的解决方案可能更好。绝对最佳的解决方案将更加通用,形式如下:

Current<T> (IQueryable<T> collection, string field) { return entity with max field of collection } 

帮助将不胜感激,我已经尝试了很长时间了,我确信它必须是可能的,因为LINQ本身的内部功能--Any,First,Count,Max--如果需要也可以保持可查询。 / p>

更新

目前,以下工作:

 Expression<Func<Product, ProductLocationHistory>> expression = IQueryable.Current(null);
        var ken = productService.GetAllProducts()
            .Where(p => p.OnLoan)
            .Select(expression)
            .Where(plh => plh.Storehouse != null)
            .Select(plh => plh.Storehouse)
            .Distinct();

public static Expression<Func<Product, ProductLocationHistory>> Current(this EntitySet<ProductLocationHistory> productLocationHistories)
    {
        Expression<Func<Product, ProductLocationHistory>> expression = p => p.ProductLocationHistories
                                         .SingleOrDefault(plh => plh.DateCreation == p.ProductLocationHistories.Max(plhs => plhs.DateCreation));
        return expression;
    }

朝着正确方向迈出的一步,但我还没有完全满意。我希望能够使用p.ProductLocationHistories()。Current()所以我的任务继续。

非常感谢Kirill!这是我第一次看到C#代码翻译成SQL!朝着正确的方向迈出了一大步!

1 个答案:

答案 0 :(得分:1)

您可以使用表达式设置字段:

Expression<Func<ProductLocationHistory, bool>> currentSelector = plh => plh.DateCreation == p.ProductLocationHistories.Max(grp => grp.DateCreation)

并在任何地方使用它:

var storehousesWithBorrowedItems = productService.GetAllProducts()
    .Select(p => p.ProductLocationHistories
        .SingleOrDefault(currentSelector ))
    .Select(plh => plh.Storehouse)
    .Distinct();