【问题标题】:NHibernate / MySQL string concatenationNHibernate / MySQL 字符串连接
【发布时间】:2026-02-09 22:05:01
【问题描述】:

我有一个如下所示的休眠 linq 查询:

 from b in session.Query<Bookmark>()
where b.Uri.Equals(uri) ||
      b.Uri.Equals("www." + uri) ||
string.Concat("www.", b.Uri).Equals(uri)
select b

这会爆炸,说不支持 Concat,但是当我将其更改为

 from b in session.Query<Bookmark>()
where b.Uri.Equals(uri) ||
      b.Uri.Equals("www." + uri) ||
      ("www." + b.Uri).Equals(uri)
select b

它运行良好,但查询看起来像这样:

select cast(count(*) as SIGNED) as col_0_0_ 
 from bookmarks bookmark0_ 
 where bookmark0_.Uri = 'www.google.com' 
    or bookmark0_.Uri = 'www.www.google.com'
    or 'www.'+bookmark0_.Uri = 'www.google.com';

“添加”了 'www.'+bookmark0_.Uri 而不是 concat('www.',bookmark0_.Uri)。有没有办法在 Linq for NHibernate for MySQL 中连接字符串?

【问题讨论】:

  • 查看正确答案here,但他们使用的是标准api

标签: c# mysql nhibernate linq-to-nhibernate


【解决方案1】:

下面是解决这个问题的HqlGenerator:

public class ConcatHqlGenerator : BaseHqlGeneratorForMethod
{
    public ConcatHqlGenerator()
        : base()
    {
        this.SupportedMethods = new[] 
        { ReflectionHelper.GetMethodDefinition(() => string.Concat(null, null)) };
    }

    public override HqlTreeNode BuildHql(MethodInfo method,
Expression targetObject,
ReadOnlyCollection<Expression> arguments,
HqlTreeBuilder treeBuilder,
IHqlExpressionVisitor visitor)
    {
        return treeBuilder.Concat(
            new[] 
            {
                visitor.Visit(arguments[0]).AsExpression(),
                visitor.Visit(arguments[1]).AsExpression()
            });
    }
}

将此添加到您的 HQLGeneratorsRegistry 中,您将可以很好地在 LINQ 语句中调用 string.Concat。

public class LinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
    public LinqToHqlGeneratorsRegistry()
        : base()
    {
        this.Merge(new ConcatHqlGenerator());
    }
}
private static ISessionFactory CreateSessionFactory()
{
    var configuration = new NHib.Cfg.Configuration();
    configuration.Properties.Add(NHibernate.Cfg
                                           .Environment.LinqToHqlGeneratorsRegistry, 
typeof(LinqToHqlGeneratorsRegistry).AssemblyQualifiedName);
    configuration.Configure();
    return configuration.BuildSessionFactory();
}

【讨论】:

  • 此解决方案从 b in session.Query() where b.Uri.Equals(uri) || 获取查询b.Uri.Equals("www." + uri) || string.Concat("www.", b.Uri).Equals(uri) 选择 b;工作,谢谢特拉维斯!
  • 如果您使用的不是字符串,这将起作用:treeBuilder.Cast(visitor.Visit(arguments[0]).AsExpression(),typeof(string))
  • 或者更好:arguments[0].Type==typeof(string)? visitor.Visit(arguments[0]).AsExpression(): treeBuilder.Cast(visitor.Visit(arguments[0]).AsExpression(),typeof(string))
【解决方案2】:

那是因为两种类型的连接。也许你可以试试 string.Concat("www" + b.Uri.ToString);

【讨论】:

  • 看来 nhib linq 对函数 String.Concat 一无所知,但它是可扩展的,因此您可以实现 Concat 以便 linq 理解它
  • jjjjj,你有如何编写 linq 重载函数的示例吗?
  • dipti-mehta,它们都是字符串类型,在数据库中,uri 是一个 varchar... 问题在于 mysql 如何处理字符串连接,与 SQL 服务器不同,您必须使用 concat 函数NHibernate 在 linq 的尝试中似乎没有意识到这一点......然而