C# LINQ到实体通用==解决方法
我有以下LINQ到实体查询C# LINQ到实体通用==解决方法,c#,entity-framework,entity-framework-4,linq-to-entities,C#,Entity Framework,Entity Framework 4,Linq To Entities,我有以下LINQ到实体查询 IQueryable<History<T>> GetFirstOperationsForEveryId<T> (IQueryable<History<T>> ItemHistory) { var q = (from h in ItemHistory where h.OperationId == (from h1 in ItemHisto
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;
}
最后,我希望一个通用查询能够处理任何可转换为历史记录的实体集合
问题是由于内部查询中的泛型ID比较(运算符“==”不能应用于“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;
}
IQueryable GetFirstOperationsForEveryId
(IQueryable项目历史记录)
{
var grouped=(从ItemHistory中的h1开始)
将h1按h1.GenericId分组为tt
选择新的
{
GenericId=tt.Key,
OperationId=tt.Min(ttt=>ttt.OperationId)
});
var q=(从ItemHistory中的h开始)
分组加入g
关于新的{h.OperationId,h.GenericId}
等于新的{g.OperationId,g.GenericId}
选择h);
返回q;
}
它之所以能够编译,是因为GenericId与equals
关键字相比较,它可以工作,但使用真实数据的查询速度太慢(它在专用的postgresql server上已经运行了11个小时)
可以选择为外部where语句构建一个完整的表达式。但代码太长,也不清楚
在LINQ to entities中,是否存在与泛型进行相等比较的简单解决方法?IQueryable GetFirstOperationsForEveryId
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;
}
(IQueryable项目历史记录)
{
var grouped=(从ItemHistory中的h1开始)
按h1.GenericId将t分组为tt
选择新的
{
GenericId=tt.Key,
OperationId=tt.Min(ttt=>ttt.OperationId)
});
var q=(从ItemHistory中的h开始)
分组加入g
关于新的{h.OperationId,h.GenericId}
等于新的{g.OperationId,g.GenericId}
选择h);
返回q;
}
试试这个,我认为它应该可以实现您想要的功能,而不需要额外的查询/连接
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;
}
IQueryable GetFirstOperationsForEveryId
(IQueryable项目历史记录)
{
var q=项目历史记录中的h
h组由h.GenericId分为tt组
设first=(从tt中的t开始)
orderby t.GenericId
选择t).FirstOrDefault()
首先选择;
返回q;
}
您还可以为实现GenericId和OperationId属性的IItemHistory接口在T上设置泛型约束。我的问题已经包含了一个解决方案。第二种方法是group+join,如果表的索引正确。从数据库表中检索370k行需要3.28秒。事实上,在非泛型变量中,postgresql上的第一个查询比第二个查询慢。26.68秒对4.75秒。与我发布的有什么区别?非常优雅的解决方案!但不幸的是,Npgsql尚未实现(从2.0.11.92开始)<代码>System.Data.EntityCommand编译异常:准备命令定义时出错。-->System.NotImplementedException:方法或操作未实现。
我的实际问题是忘记创建索引。这就是为什么group+join查询工作了11个小时。有了索引,它运行得相当快。
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;
}