问题描述
|
我对此查询有疑问:
var idsToFetch = new int[] {1,2};
var q = from t in session.Query<Thing>()
where idsToFetch.Contains(t.Id)
let lastTask = (from task in session.Query<ReportTask>()
where task.Thang.Id == t.Id
orderby task.Id descending
select task).FirstOrDefault()
select new {
Id = t.Id,Errors = lastTask.Results.Sum(r => r.Errors)
};
var errors = q.FirstOrDefault().Errors;
用英语:
Please,for these \"Thangs\",give me their last total error count.
与模型:
public class Thing
{
public virtual int Id { get; set; }
}
public class ReportTask
{
public virtual int Id { get; set; }
public virtual Thing Thang { get; set; }
public virtual ICollection<ReportResult> Results { get; set; }
}
public class ReportResult
{
public virtual int Id { get; set; }
public virtual ReportTask Task { get; set; }
public virtual int Errors { get; set; }
}
这是对我在现实世界项目中面临的确切问题的模拟。尝试分配errors
时出现此错误:
类型异常
\'Antlr.Runtime.NoViableAltException \'
被扔了。
[.FirstOrDefault [<>f_AnonymousType22[[System.Int32,mscorlib,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089],[System.Int32,PublicKeyToken=b77a5c561934e089]]](.Select[<>f__AnonymousType1
2[[TestWeb.CSharp.Models.Thing,
TestWeb.CSharp,版本= 1.0.0.0,
文化=中立,
PublicKeyToken = null],[TestWeb.CSharp.Models.ReportTask,
TestWeb.CSharp,版本= 1.0.0.0,
文化=中立,
PublicKeyToken = null]],<>f_AnonymousType22[[System.Int32,PublicKeyToken=b77a5c561934e089]]](.Select[TestWeb.CSharp.Models.Thing,<>f__AnonymousType1
2[[TestWeb.CSharp.Models.Thing,
TestWeb.CSharp,版本= 1.0.0.0,
文化=中立,
PublicKeyToken = null],[TestWeb.CSharp.Models.ReportTask,
TestWeb.CSharp,版本= 1.0.0.0,
文化=中立,
PublicKeyToken = null]]](。Where [TestWeb.CSharp.Models.Thing](NHibernate.Linq.NhQueryable1[TestWeb.CSharp.Models.Thing],Quote((t,) =>
(.Contains[System.Int32](p1,t.Id,))),),) => (new
<>f__AnonymousType1
2(t,
.FirstOrDefault [TestWeb.CSharp.Models.ReportTask](。OrderByDescending [TestWeb.CSharp.Models.ReportTask,System.Int32](。Where [TestWeb.CSharp.Models.ReportTask](NHibernate.Linq.NhQueryable1[TestWeb.CSharp.Models.ReportTask],Quote((task,) =>
(Equal(task.Thang.Id,t.Id))),) => (task.Id)),Quote((<>h__TransparentIdentifier0,)
=> (new <>f__AnonymousType2
2(<> h_TransparentIdentifier0。 t.Id
OrElse(等于(<> h_TransparentIdentifier0.lastTask,
空值),
等于(<> h_TransparentIdentifier0.lastTask.Results,
空值)) ? p2:
.Sum [TestWeb.CSharp.Models.ReportResult](<> h_TransparentIdentifier0.lastTask.Results,
(r,)=>(r.Errors,),))),),)]
我为此查询尝试了多种其他格式,包括:
from x in x
where y.Contains(x.Id)
select ((from ... subquery).FirstOrDefault())
这使我走得更远,因为这样的查询是在SQL中进行的:
select (select
thing0_.Id,(select cast(sum(results2_.Errors) as INTEGER)
from \"ReportResult\" results2_
where reporttask1_.Id=results2_.ReportTask_id)
from \"ReportTask\" reporttask1_
where reporttask1_.Thang_id=thing0_.Id
order by reporttask1_.Id desc) as col_0_0_
from \"Thing\" thing0_
where thing0_.Id in (1,2)
limit 1
这在语法上是不正确的,在SQLLite中,我得到:
SQLite错误
仅单个结果允许作为表达式一部分的SELECT
在SQL Server 2008(我使用的是我的真实数据库)中,这是一个非常相似的错误,关于子查询不允许使用多个表达式。
因此,我觉得自己真的很接近答案,但是我无法完全解决问题。有任何想法吗?
PS。在使用Linq-2-SQL的LINQPad中,此查询工作正常。
PSS。我无法使用Criteria
进行此查询,因为我很讨厌Criteria。奖励指向使这个婴儿按标准工作的人...如果LINQ不可行,我完全同意。
解决方法
我最终将我的SQL查询放入数据库视图中,并只是针对该查询进行查询,以防止我使用NHibernate的LINQ实现拉扯我的头发。如果有人想回来告诉我这样做的“正确”方法,请这样做!