Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Czy można użyć `SqlDbType.Structured` do przekazywania parametrów wycenianych w tabeli w NHibernate?

Moim pierwszym, doraźnym pomysłem było zaimplementowanie własnego 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...
}

Nie wdrożono więcej metod; a throw new NotImplementedException(); jest w całej reszcie. Następnie stworzyłem proste rozszerzenie dla 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);
    }
}

Typowe zastosowanie dla mnie to

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

Ok, ale czym jest "IntTable" ? Jest to nazwa typu SQL stworzona do przekazywania argumentów wartości tabeli.

CREATE TYPE IntTable AS TABLE
(
    ID INT
);

I some_sp może być jak

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

Oczywiście działa tylko z Sql Server 2008 iw tej konkretnej implementacji z jednokolumnowym DataTable .

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

To tylko POC, a nie kompletne rozwiązanie, ale działa i może być przydatne po dostosowaniu. Jeśli ktoś zna lepsze/krótsze rozwiązanie, daj nam znać.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Zwróć nazwę bieżącej stacji roboczej, która jest połączona z programem SQL Server (T-SQL)

  2. SQL Server 2008 Pusty ciąg a spacja

  3. 10 najczęściej zadawanych pytań dotyczących monitorowania wydajności serwera SQL

  4. Proaktywne kontrole stanu serwera SQL, część 1:Miejsce na dysku

  5. Nie można załadować biblioteki DLL „SqlServerSpatial.dll”