我有以下LINQ到实体查询
IQueryable<History<T>> GetFirstOperationsForEveryId<T>
(IQueryable<History<T>> 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
是一般通用查询。它可以通过以下方式获得
var history1 = MyEntitiySet1.Select(obj =>
new History<long>{ obj.OperationId, GenericId = obj.LongId });
var history2 = AnotherEntitiySet.Select(obj =>
new History<string>{ obj.OperationId, GenericId = obj.StringId });
最后,我想要一个通用查询能够处理任何可转换为History<T>
的实体集合。
问题是代码无法编译,因为内部查询中的GenericId比较(运算符'=='不能应用于'T'和'T'类型的操作数。)
如果我将==更改为h1.GenericId.Equals(h.GenericId)
,我会收到以下NotSupportedException
:
无法将类型'System.Int64'强制转换为'System.Object'类型。 LINQ to Entities仅支持转换实体数据模型基元类型。
我尝试过分组而不是子查询并加入结果。
IQueryable<History<T>> GetFirstOperationsForEveryId<T>
(IQueryable<History<T>> 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中的泛型进行相等比较?
答案 0 :(得分:1)
试试这个,我认为它应该在没有额外查询/加入的情况下完成你想要的东西
IQueryable<History<T>> GetFirstOperationsForEveryId<T>
(IQueryable<History<T>> 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;
}
答案 1 :(得分:0)
IQueryable<History<T>> GetFirstOperationsForEveryId<T>
(IQueryable<History<T>> 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;
}
答案 2 :(得分:0)
您还可以为实现GenericId和OperationId属性的Item History接口设置T的通用约束。
答案 3 :(得分:0)
我的问题已经包含一个解决方案。如果表已正确编入索引,则使用group + join的第二种方法效果很好。从数据库表中检索370k行需要3.28秒。事实上,在非泛型变体中,postgresql上的第一个查询比第二个查询慢。 26.68秒vs 4.75。