私はPHPを使用してASP .NETコアにアップグレードします。Entity Frameworkコアの別のテーブルから最新のレコードを効率的に結合する
問題: T: {ID, Description, FK}
とStates: {ID, ID_T, Time, State}
:図について
、次の2つの表を想定。それらの間には1:nの関係があります(ID_T
参照T.ID
)。
私はStates
で関連する最新のレコード(もしあれば)と一緒に(1
を言うことができます)FK
のいくつかの特定の値でT
からすべてのレコードを必要としています。それはのように記述することができるSQLの面では
:
SELECT T.ID, T.Description, COALESCE(s.State, 0) AS 'State' FROM T
LEFT JOIN (
SELECT ID_T, MAX(Time) AS 'Time'
FROM States
GROUP BY ID_T
) AS sub ON T.ID = sub.ID_T
LEFT JOIN States AS s ON T.ID = s.ID_T AND sub.Time = s.Time
WHERE FK = 1
私は、LINQでの効率的な同等のクエリ(または流暢API)を書くのに苦労しています。私がこれまで持っている最高の実用的なソリューションは、次のとおりです。
from t in _context.T
where t.FK == 1
join s in _context.States on t.ID equals o.ID_T into _s
from s in _s.DefaultIfEmpty()
let x = new
{
id = t.ID,
time = s == null ? null : (DateTime?)s.Time,
state = s == null ? false : s.State
}
group x by x.id into x
select x.OrderByDescending(g => g.time).First();
それだけのようなものを実行するとき、私は出力ウィンドウに結果のSQLクエリをチェックすると:それはより多くの列を選択する
SELECT [t].[ID], [t].[Description], [t].[FK], [s].[ID], [s].[ID_T], [s].[Time], [s].[State]
FROM [T] AS [t]
LEFT JOIN [States] AS [s] ON [T].[ID] = [s].[ID_T]
WHERE [t].[FK] = 1
ORDER BY [t].[ID]
だけでなく、私が必要とするよりも(実際のスキームにはもっと多くのものがあります)。 クエリーにグルーピングがないので、DBからすべてを選択すると思います(そして、States
は巨大になります)、グルーピング/フィルタリングはDB外で行われています。
質問:
あなたは何をしますか?
- LINQ/Fluent APIに効率的なクエリがありますか?
- そうでない場合は、どのような回避策を使用できますか?
- 生SQLは、特定のDB技術から抽象化の概念を遺跡とその使用は、現在のEntity Frameworkのコア(多分その最善の解決策)に非常に不格好です。
- 私にとって、これはデータベースビューを使用する良い例のようです。エンティティフレームワークコアでサポートされていません(しかし、おそらくその最高のソリューションです)。
「効率性」と「エンティティフレームワーク」は合わない。 – nurdyguy
EF Core group byはメモリ内で行われます。 EFコアの注文は、ストリーミングを許可するためにグループ化キーを生成し、グループ化しないで効率的なグループをサーバーに送信します。追跡に関する問題https://github.com/aspnet/EntityFramework/issues/2341 – Smit
@Smit:ありがとうございます。私はすでにこの記事を見つけました:https://jonhilton.net/2016/11/09/is-entity-framework-core-production-ready/ 私はEF6に切り替えようとします –