在Concat投影中使用Cast Projection

时间:2014-11-09 18:27:02

标签: nhibernate projection queryover

我有以下查询:

var result = _session.QueryOver<Entity>()
    .Where(e => e.Property == value)
    .SelectList(list => list
        .Select(f => Projections.Concat("prefix-", e.BigIntProperty)).WithAlias(() => alias.Whatever)
        ...
    )
    .TransformUsing(Transformers.AliasToBean<Model>())
    .Future<Model>();

问题是Projections.Concat()只接受字符串而且e.BigIntProperty不接受,上面的内容不会编译。有没有办法将e.BigIntProperty转换为字符串?

我尝试了类似下面的内容,但它们都不起作用:

.Select(f => Projections.Concat("prefix-", Projection.Cast(NHibernateUtil.String, e.BigIntProperty))).WithAlias(() => alias.Whatever)

,因为Projections.Cast会返回IProjection而不是字符串。

2 个答案:

答案 0 :(得分:3)

Projections.Cast似乎非常有限,因为它不能随意Projection。幸运的是,您可以轻松创建自己的自定义投影,使您能够这样做:

public static class CustomProjections
{
    public static IProjection Concat(params IProjection[] projections)
    {
        return Projections.SqlFunction(
            "concat",
            NHibernateUtil.String,
            projections);
    }
}

然后,您就可以像这样使用CustomProjections课程了:

var result = _session.QueryOver<Entity>()
    .Where(e => e.Property == value)
    .SelectList(list => list
        .Select(CustomProjections.Concat(
            Projections.Constant("prefix-"),
            Projections.Cast(
                NHibernateUtil.String,
                Projections.Property<Entity>(e => e.BigIntProperty))))
            .WithAlias(() => alias.Whatever)
        ...
    )
    .TransformUsing(Transformers.AliasToBean<Model>())
    .Future<Model>();

答案 1 :(得分:2)

我已经接受了安德鲁的答案,但仅供参考,您可以直接使用Projections.SqlFunction("concat", ...)解决整个问题,因为它可以将IProjection作为参数而不仅仅是字符串。

var result = _session.QueryOver<Entity>()
    .Where(e => e.Property == value)
    .SelectList(list => list
        .Select(Projections.SqlFunction("concat",
            NHibernateUtil.String,
            Projections.Constant("prefix-"),
            Projections.Cast(NHibernateUtil.String, Projections.Property<Entity>(e => e.BigIntProperty))))               
        .WithAlias(() => alias.Whatever)
        ...
     )
    .TransformUsing(Transformers.AliasToBean<Model>())
    .Future<Model>();

注意:似乎在调用Projections.Concat(...)Projections.SqlFunction("concat", ...)时,生成的查询实际上使用+运算符,例如:

SELECT (a + b) as foo FROM table

而不是:

SELECT concat(a, b) as foo FROM table

当然,CONCAT仅适用于MS SQL Server 2012及更高版本,因此这是正确的。可能MsSQl2012Dialect可以使用CONCAT,因为 CONCAT不要求参数是varchar,它们也可能是整数

不幸的是MsSQl2012Dialect没有这样做,但是构建自定义方言非常容易:

public class CustomMsSql2012Dialect : MsSql2012Dialect
{
    protected override void RegisterFunctions()
    {
        base.RegisterFunctions();
        base.RegisterFunction("concat", new VarArgsSQLFunction(NHibernateUtil.String, "concat(", ",", ")"));
    }
}

因此,如果您使用的是2012版或更高版本并且您将上述内容声明为Dialect,则可以放弃Projections.Cast(...)部分