私は以下のLINQ-to-entitiesクエリを持っています
IQueryable> GetFirstOperationsForEveryId
(IQueryable> ItemHistory)
{
var q = (from h in ItemHistory
where h.OperationId ==
(from h1 in ItemHistory
where h1.GenericId == h.GenericId
select h1.OperationId).Min()
select h);
return q;
}
ItemHistory
is a generic query. It can be obtained in the following way
var history1 = MyEntitiySet1.Select(obj =>
new History{ obj.OperationId, GenericId = obj.LongId });
var history2 = AnotherEntitiySet.Select(obj =>
new History{ obj.OperationId, GenericId = obj.StringId });
In the end of all I want a generic query being able to work with any entity collection convertible to History
.
問題は、内部クエリのGenericId比較のためにコードがコンパイルされないということです(オペレータ '=='は 'T'および 'T'タイプのオペランドに適用できません)。
==を h1.GenericId.Equals(h.GenericId)
に変更すると、次の NotSupportedException
が表示されます。
タイプ 'System.Int64'をタイプして 'System.Object'にキャストすることができません。エンティティへのLINQは、エンティティデータモデルプリミティブ型のキャストのみをサポートします。
サブクエリの代わりにグループ化を行い、結果に参加しようとしました。
IQueryable> GetFirstOperationsForEveryId
(IQueryable> ItemHistory)
{
var grouped = (from h1 in ItemHistory
group h1 by h1.GenericId into tt
select new
{
GenericId = tt.Key,
OperationId = tt.Min(ttt => ttt.OperationId)
});
var q = (from h in ItemHistory
join g in grouped
on new { h.OperationId, h.GenericId }
equals new { g.OperationId, g.GenericId }
select h);
return q;
}
GenericIdは equals
キーワードと比較され、動作しますが、実際のデータを持つクエリは遅すぎます(専用のpostgresqlサーバーで11時間実行されています)。
外側のwhereステートメントのための完全な式を構築するオプションがあります。しかし、このコードは長すぎて不明瞭です。
LINQ-to-entitiesのジェネリックとの等価比較の簡単な回避策はありますか?
これを試してみてください。余分なクエリ/結合なしであなたが望むものを達成しなければならないと思います
IQueryable> GetFirstOperationsForEveryId
(IQueryable> ItemHistory)
{
var q = from h in ItemHistory
group h by h.GenericId into tt
let first = (from t in tt
orderby t.GenericId
select t).FirstOrDefault()
select first;
return q;
}
IQueryable> GetFirstOperationsForEveryId
(IQueryable> ItemHistory)
{
var grouped = (from h1 in ItemHistory
group t by h1.GenericId into tt
select new
{
GenericId = tt.Key,
OperationId = tt.Min(ttt => ttt.OperationId)
});
var q = (from h in ItemHistory
join g in grouped
on new { h.OperationId, h.GenericId }
equals new { g.OperationId, g.GenericId }
select h);
return q;
}