我有这个LINQ查询:
var q =
from defect in DataService.Query<Defect>()
join defectSize in DataService.Query<DefectSize>() on defect.DefectSize.Id equals defectSize.Id
where defectSize.UserCode == "def1"
select defect;
我想要的只是在运行时创建这个查询并将其传递给NHibernate执行,我想创建并复制该表达式的树。
让我们首先看一下编译器创建的表达式树:
.Call System.Linq.Queryable.Select(
.Call System.Linq.Queryable.Where(
.Call System.Linq.Queryable.Join(
.Constant<NHibernate.Linq.NhQueryable`1[ObjectModel.Defect.Defect]>(NHibernate.Linq.NhQueryable`1[ObjectModel.Defect.Defect]),
.Constant<NHibernate.Linq.NhQueryable`1[ObjectModel.Defect.DefectSize]>(NHibernate.Linq.NhQueryable`1[ObjectModel.Defect.DefectSize]),
'(.Lambda #Lambda1<System.Func`2[ObjectModel.Defect.Defect,System.Int32]>),
'(.Lambda #Lambda2<System.Func`2[ObjectModel.Defect.DefectSize,System.Int32]>),
'(.Lambda #Lambda3<System.Func`3[ObjectModel.Defect.Defect,ObjectModel.Defect.DefectSize,<>f__AnonymousType0`2[ObjectModel.Defect.Defect,ObjectModel.Defect.DefectSize]]>))
,
'(.Lambda #Lambda4<System.Func`2[<>f__AnonymousType0`2[ObjectModel.Defect.Defect,ObjectModel.Defect.DefectSize],System.Boolean]>))
,
'(.Lambda #Lambda5<System.Func`2[<>f__AnonymousType0`2[ObjectModel.Defect.Defect,ObjectModel.Defect.DefectSize],ObjectModel.Defect.Defect]>))
.Lambda #Lambda1<System.Func`2[ObjectModel.Defect.Defect,System.Int32]>(ObjectModel.Defect.Defect $defect) {
($defect.DefectSize).Id
}
.Lambda #Lambda2<System.Func`2[ObjectModel.Defect.DefectSize,System.Int32]>(ObjectModel.Defect.DefectSize $defectSize) {
$defectSize.Id
}
.Lambda #Lambda3<System.Func`3[ObjectModel.Defect.Defect,ObjectModel.Defect.DefectSize,<>f__AnonymousType0`2[ObjectModel.Defect.Defect,ObjectModel.Defect.DefectSize]]>(
ObjectModel.Defect.Defect $defect,
ObjectModel.Defect.DefectSize $defectSize) {
.New <>f__AnonymousType0`2[ObjectModel.Defect.Defect,ObjectModel.Defect.DefectSize](
$defect,
$defectSize)
}
.Lambda #Lambda4<System.Func`2[<>f__AnonymousType0`2[ObjectModel.Defect.Defect,ObjectModel.Defect.DefectSize],System.Boolean]>(<>f__AnonymousType0`2[ObjectModel.Defect.Defect,ObjectModel.Defect.DefectSize] $<>h__TransparentIdentifier0)
{
($<>h__TransparentIdentifier0.defectSize).UserCode == "ext1"
}
.Lambda #Lambda5<System.Func`2[<>f__AnonymousType0`2[ObjectModel.Defect.Defect,ObjectModel.Defect.DefectSize],ObjectModel.Defect.Defect]>(<>f__AnonymousType0`2[ObjectModel.Defect.Defect,ObjectModel.Defect.DefectSize] $<>h__TransparentIdentifier0)
{
$<>h__TransparentIdentifier0.defect
}
如您所见,为了表示连接和where子句,编译器创建匿名类型&lt;&gt; f__AnonymousType0`2 以包含两个连接成员,它实例化类和具有 New 表达式的成员,然后在where子句中,它使用&lt;&gt; h__TransparentIdentifier0 来表示where。
好吧,我已经复制了所有这个树,在我的代码中我在运行时创建了一个动态类型,在编译器创建的类型上找到了确切的成员,我的表达式树看起来等于这里发布的那个,但是当我尝试实现查询,NH抛出 NotSupportedException !
有趣的是,如果我第一次执行: q.ToArray(),q是编译器创建的表达式树,然后我做 myTree.ToArray()< / em>在这种情况下它很有效!解释是,第二次,执行我的树NH使用先前创建的查询计划,这表明它认为两个查询是相同的!
我通过查看NH源代码尝试了一些调查尝试,我发现NH通过使用中的 NhRelinqQueryParser.Parse(_expression)方法从表达式创建查询模型> NHibernate.Linq.NhLinqExpression ,在这里我发现两个模型不同,确切的模型应该是:
from Defect defect in value(NHibernate.Linq.NhQueryable`1[ObjectModel.Defect.Defect]) join DefectSize defectSize in value(NHibernate.Linq.NhQueryable`1[ObjectModel.Defect.DefectSize]) on [defect].DefectSize.Id equals [defectSize].Id where ([defectSize].UserCode == \"def1\") select [defect]
但是我的表情变成了:
from Defect defect in value(NHibernate.Linq.NhQueryable`1[ObjectModel.Defect.Defect]) join DefectSize defectSize in value(NHibernate.Linq.NhQueryable`1[ObjectModel.Defect.DefectSize]) on [defect].DefectSize.Id equals [defectSize].Id where (new <>f__AnonymousType0`2([defect], [defectSize]).defectSize.UserCode == \"def1\") select new <>f__AnonymousType0`2([defect], [defectSize]).defect
在这里我放弃了,我无法进一步调试到远程类。
如果您有任何线索,我会感激任何提示。我正在使用NH 3.3.3 GA
感谢阅读。