sql >> Databáze >  >> RDS >> Sqlserver

Je možné použít `SqlDbType.Structured` k předání parametrů s hodnotou tabulky v NHibernate?

Můj první, ad hoc, nápad byl implementovat můj vlastní 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...
}

Nejsou implementovány žádné další metody; a throw new NotImplementedException(); je ve všem ostatním. Dále jsem vytvořil jednoduché rozšíření pro 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);
    }
}

Typické použití pro mě je

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

Dobře, ale co je "IntTable" ? Je to název typu SQL vytvořeného pro předávání argumentů hodnot tabulky.

CREATE TYPE IntTable AS TABLE
(
    ID INT
);

A some_sp může být jako

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

Funguje samozřejmě pouze se Sql Server 2008 a v této konkrétní implementaci s jednosloupcovou DataTable .

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

Je to pouze POC, není to úplné řešení, ale funguje a může být užitečné, když je přizpůsoben. Pokud někdo zná lepší/kratší řešení, dejte nám vědět.



  1. Tipy k tabulce Microsoft Access – triky a pokyny, část 5

  2. Zadanému názvu a typu argumentu neodpovídá žádný operátor. Možná budete muset přidat explicitní přetypování. -- Netbeans, Postgresql 8.4 a Glassfish

  3. SQLite JSON()

  4. Jak odesílat e-maily pomocí Oracle 10 g Forms