NHibernate / MySQL 字符串拼接

5

我有一个类似这样的nhibernate 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';

在Linq for NHibernate for MySQL中,是否有一种方法可以连接字符串,而不是使用concat('www.',bookmark0_.Uri),将'www.'+bookmark0_.Uri“添加”?

请参考此处的正确答案,但他们使用的是 Criteria API。 - jjjjj
2个回答

6
以下是一个解决此问题的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();
}

这个解决方案成功运用了Travis的建议,从session.Query<Bookmark>()中获取了查询条件: where b.Uri.Equals(uri) || b.Uri.Equals("www." + uri) || string.Concat("www.", b.Uri).Equals(uri) select b; - Andrew Boyd
如果您使用的不是字符串,则可以使用以下代码:treeBuilder.Cast(visitor.Visit(arguments[0]).AsExpression(),typeof(string)) - AlexDev
或者更好的方法:arguments [0] .Type == typeof(string)? visitor.Visit(arguments [0]).AsExpression():treeBuilder.Cast(visitor.Visit(arguments [0]).AsExpression(),typeof(string)) - AlexDev

0

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


似乎 NHibernate 的 LINQ 不了解 String.Concat 函数,但它是可扩展的,因此您可以实现 Concat 以让 LINQ 理解它。 - jjjjj
jjjjj,你有写Linq重载函数的示例吗? - Andrew Boyd
dipti-mehta,它们都是字符串类型并且在数据库中,uri 是 varchar 类型... 问题在于 mysql 如何处理字符串连接,不像 SQL Server,你必须使用 concat 函数,而 NHibernate 在尝试使用 Linq 时似乎无法识别它... - Andrew Boyd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接