21

NHibernate を使用してマップされるストアド プロシージャに ID のコレクションを渡したいと考えています。この手法は、Sql Server 2008 で導入されました (詳細はこちら =>テーブル値パラメーター)。nvarcharパラメータ内で複数の ID を渡してから、SQL Server 側でその値をチョップしたくないだけです。

4

4 に答える 4

36

私の最初のアドホックなアイデアは、独自の を実装することでした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(DbCommand 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...
}

これ以上のメソッドは実装されていません。athrow new NotImplementedException();は残りのすべてです。次に、 の簡単な拡張機能を作成しました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);
    }
}

私の典型的な使い方は

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>();

わかりましたが、 とは何"IntTable"ですか? テーブル値の引数を渡すために作成された SQL 型の名前です。

CREATE TYPE IntTable AS TABLE
(
    ID INT
);

そしてsome_sp、次のようになる可能性があります

CREATE PROCEDURE some_sp
    @id IntTable READONLY,
    @par1 ...
AS
BEGIN
...
END

もちろん、Sql Server 2008でのみ機能し、この特定の実装では単一列DataTable.

var dt = new DataTable();
dt.Columns.Add("ID", typeof(int));

これは POC のみであり、完全なソリューションではありませんが、機能し、カスタマイズすると役立つ場合があります。誰かがより良い/より短い解決策を知っている場合はお知らせください。

于 2010-09-27T19:08:32.413 に答える
2

手間をかけずに値のコレクションを渡すことができます。

例:

var ids = new[] {1, 2, 3};
var query = session.CreateQuery("from Foo where id in (:ids)");
query.SetParameterList("ids", ids);

Hibernate は各要素のパラメーターを作成します。

于 2010-09-13T15:52:52.783 に答える