私は今、簡単な問題で丸2日間いじっています。
Product エンティティと ProductLocationHistory エンティティを含むデータベースがあります。ProductLocationHistory には、Storehouse、Contact、または Relation への参照があります。製品が移動するたびに新しいエントリが取得されるため、製品の過去をたどることができます。したがって、現在の場所は、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));
}
「Current has no supported translation to sql」が表示されるため、これはクエリ可能では機能しません。また、Product と ProductLocationHistory の組み合わせがクエリの「開始」であることが多いため、すぐに IEnumerable に変換するのではなく、IQueryable のままにしてクエリを実行する必要があります。商品ごとに現在地を特定!その後に何が続くかは言うまでもありません...エンティティの現在のログエントリはよく使用され、機能し、クエリ可能である限り、.Current() 関数がどれほど複雑であっても問題ありません。基になるコードがクエリ可能であるため、.Current(...) 関数が機能することを期待していましたが、それでも例外が発生します。最初の例のようにコードがインラインの場合、例外は発生しません。
Func、ProductLocationHistory>>、および Expression<...> などの可能性を調べましたが、探している例が見つかりませんでした。Product.CurrentProductLocationHistory() のようなソリューションは、さらに優れている可能性があります。絶対的な最善の解決策は、さらに一般的で、次の形式になります。
Current<T> (IQueryable<T> collection, string field) { return entity with max field of collection }
私はこれを長い間試してきましたが、LINQ自体の内部関数(Any、First、Count、Max)も必要に応じてクエリ可能であるため、可能であるに違いないと確信しています。
アップデート
現在、次のように動作します。
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() を使用できるようにしたいので、探求を続けます。
ありがとうキリル!C# コードが SQL に変換されたのを見たのはこれが初めてです。正しい方向への素晴らしい一歩!