使用NHibernate

时间:2015-10-01 09:21:20

标签: linq nhibernate

我有这个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

感谢阅读。

0 个答案:

没有答案