簡體   English   中英

將 LINQ 擴展到 Nhibernate 提供程序,並結合動態 LINQ 問題

[英]Extending LINQ to Nhibernate provider, in combination with Dynamic LINQ problem

我正在使用 NHibernate 3.1.0 並且我正在嘗試通過使用BaseHqlGeneratorForMethod並擴展DefaultLinqToHqlGeneratorsRegistry來擴展 LINQ 提供程序,如Fabio 的帖子中所述。

例如,為了支持ToString() ,我創建了一個ToStringGenerator ,如下所示。

internal class ToStringGenerator : BaseHqlGeneratorForMethod
{
    public ToStringGenerator()
    {
        SupportedMethods = new[]
            {
                ReflectionHelper.GetMethodDefinition<object>(x => x.ToString())
            };
    }

    public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
    {
        return treeBuilder.Cast(visitor.Visit(targetObject).AsExpression(), typeof(string));
    }
}

我已經注冊使用

internal class CustomLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
    public CustomLinqToHqlGeneratorsRegistry()
    {
        this.Merge(new ToStringGenerator());
    }
}

等到目前為止,這適用於“靜態”查詢,我可以像這樣使用它:

var results = mSession.Query<Project>();
string pId = "1";
results = results.Where(p => p.Id.ToString().Contains(pId));

這可以正確轉換為 SQL 對應物(使用 SQL Server 2008)

where cast(project0_.Id as NVARCHAR(255)) like (''%''+@p0+''%'')

當我嘗試將它與 Microsoft Dynamic LINQ 庫(在此 Scott Guthrie 的帖子中討論)結合使用時,就會出現問題,如下所示:

var results = mSession.Query<Project>();
string pId = "1";
results = results.Where("Id.ToString().Contains(@0)", pId);

這會導致NotSupportedException帶有“ System.String ToString() ”消息(這與我在實現上述類之前通過 static 查詢得到的消息完全相同)。 此異常的來源為“ NHibernate ”,StackTrace 位於“ NHibernate.Linq.VisitorExpression.HqlGeneratorExpressionExpression .

那么我在這里缺少什么? 我做錯了什么,或者需要做什么來支持這種情況?

我遇到了同樣的問題並修復了它。
首先,我要感謝 murki 提供了讓我上路的信息!

答案部分在於法比奧的帖子。 要解決此問題,您必須在CustomLinqToHqlGeneratorsRegistry構造函數中使用RegisterGenerator而不是Merge方法。 我對CustomLinqToHqlGeneratorsRegistry class 的實現如下:

public class CustomLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
    public CustomLinqToHqlGeneratorsRegistry()
        : base()
    {
        MethodInfo toStringMethod = ReflectionHelper.GetMethodDefinition<int>(x => x.ToString());
        RegisterGenerator(toStringMethod, new ToStringGenerator());
    }
}

這里有兩個定義明確的獨立階段:

  1. 將動態(字符串)查詢轉換為 static 表達式(由 Dynamic Linq 庫完成)
  2. 將其解析為 HqlTree,然后執行(由 NHibernate 完成)

由於您已確定 static 表達式運行良好,因此問題在於1。

如果您執行以下操作會發生什么?

var results = Enumerable.Empty<Project>().AsQueryable();
string pId = "1";
results = results.Where("Id.ToString().Contains(@0)", pId);

如果它失敗了,您將確認這是 Dynamic Linq 單獨的問題(即它不支持您輸入的表達式),因此您必須深入研究並修補它。

半相關: ToStringGenerator看起來很有用; 你能為 NHibernate 提交補丁嗎? http://jira.nhforge.org

假設 class Project的屬性IdInt32 ,請嘗試在ToStringGenerator class 中注冊相應的Int32.ToString()方法。

...
public ToStringGenerator()
{
    SupportedMethods = new[]
        {
            ReflectionHelper.GetMethodDefinition<object>(x => x.ToString()),
            ReflectionHelper.GetMethodDefinition<int>(x => x.ToString()),
        };
}
...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM