我现在已经整整摆弄了两天,现在出现了一个简单的问题。
我有一个包含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!朝着正确的方向迈出了一大步!
答案 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();