是否可以使用`SqlDbType.Structured`在NHibernate中传递表值参数?

Iam*_*per 16 sql-server nhibernate table-valued-parameters

我想将一组id传递给将使用NHibernate映射的存储过程.这种技术是在Sql Server 2008中引入的(更多信息在这里=> 表值参数).我只是不想在nvarchar参数中传递多个ID ,然后在SQL Server端切断它的值.

小智 33

我的第一个临时想法是实现我自己的想法IType.

public class Sql2008Structured : IType {
    private static readonly SqlType[] x = new[] { new SqlType(DbType.Object) };
    public SqlType[] SqlTypes(NHibernate.Engine.IMapping mapping) {
        return x;
    }

    public bool IsCollectionType {
        get { return true; }
    }

    public int GetColumnSpan(NHibernate.Engine.IMapping mapping) {
        return 1;
    }

    public void NullSafeSet(IDbCommand st, object value, int index, NHibernate.Engine.ISessionImplementor session) {
        var s = st as SqlCommand;
        if (s != null) {
            s.Parameters[index].SqlDbType = SqlDbType.Structured;
            s.Parameters[index].TypeName = "IntTable";
            s.Parameters[index].Value = value;
        }
        else {
            throw new NotImplementedException();
        }
    }

    #region IType Members...
    #region ICacheAssembler Members...
}
Run Code Online (Sandbox Code Playgroud)

没有更多的方法实施; throw new NotImplementedException();其余的都是a .接下来,我创建了一个简单的扩展IQuery.

public static class StructuredExtensions {
    private static readonly Sql2008Structured structured = new Sql2008Structured();

    public static IQuery SetStructured(this IQuery query, string name, DataTable dt) {
        return query.SetParameter(name, dt, structured);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的典型用法是

DataTable dt = ...;
ISession s = ...;
var l = s.CreateSQLQuery("EXEC some_sp @id = :id, @par1 = :par1")
            .SetStructured("id", dt)
            .SetParameter("par1", ...)
            .SetResultTransformer(Transformers.AliasToBean<SomeEntity>())
            .List<SomeEntity>();
Run Code Online (Sandbox Code Playgroud)

好的,但是什么是"IntTable"?它是为传递表值参数而创建的SQL类型的名称.

CREATE TYPE IntTable AS TABLE
(
    ID INT
);
Run Code Online (Sandbox Code Playgroud)

而且some_sp也能像

CREATE PROCEDURE some_sp
    @id IntTable READONLY,
    @par1 ...
AS
BEGIN
...
END
Run Code Online (Sandbox Code Playgroud)

它仅适用于过程的SQL Server 2008和与单柱这个特定的实现DataTable.

var dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
Run Code Online (Sandbox Code Playgroud)

它只是POC,不是一个完整的解决方案,但它可以工作,并且在定制时可能很有用.如果有人知道更好/更短的解决方案,请告诉我们.