Quiero pasar una colección de identificadores a un procedimiento almacenado que se asignará utilizando NHibernate. Esta técnica se introdujo en Sql Server 2008 (más información aquí =>Table-Valued Parameters). Simplemente no quiero pasar múltiples identificadores dentro de un parámetro nvarchar
y luego cortar su valor en el lado del Servidor SQL.¿Es posible utilizar `SqlDbType.Structured` para pasar los parámetros con valores de tabla en NHibernate?
Respuesta
Mi primera idea, ad hoc, fue implementar mi propio IType
. se implementan
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...
}
métodos más; un throw new NotImplementedException();
está en el resto. A continuación, creé una extensión simple para 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);
}
}
uso típico para mí es
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, pero lo que es un "IntTable"
? Es el nombre del tipo de SQL creado para pasar argumentos de valor de tabla.
CREATE TYPE IntTable AS TABLE
(
ID INT
);
Y some_sp
podría ser como
CREATE PROCEDURE some_sp
@id IntTable READONLY,
@par1 ...
AS
BEGIN
...
END
Sólo funciona con SQL Server 2008 y, por supuesto, en esta implementación particular, con una sola columna DataTable
.
var dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
Solo es POC, no es una solución completa, pero funciona y puede ser útil cuando se personaliza. Si alguien conoce una solución mejor/más corta, háganoslo saber.
alguien sabe acerca de dos columnas DataTable? – rcarvalhoxavier
Pawel Kupis - ¿Puedes ver esta pregunta similar pero diferente: http://stackoverflow.com/questions/42228253/sqldbtype-structured-to-pass-table-valued-parameters-in-nhibernate-to-select-wit – Remy
Puede pasar colecciones de valores sin la molestia.
Ejemplo:
var ids = new[] {1, 2, 3};
var query = session.CreateQuery("from Foo where id in (:ids)");
query.SetParameterList("ids", ids);
NHibernate creará un parámetro para cada elemento.
¿No hay una limitación de 2100 parámetros? Además, no creo que sea una solución para mi necesidad :) ¿O sí? – IamDeveloper
Bueno, ¿cuántos necesitas? Es un enfoque alternativo. –
esto no resuelve el problema del parámetro 2100 –
¿Han conseguido esta implementación otros que funcionen? Necesito pasar varias filas de múltiples columnas (5 enteros para ser exactos) usando este método – Definí mi tipo subyacente de SQL estructurado y cambié el ColumnSpan
para devolver 5. La única otra diferencia que puedo ver es que no devuelvo ninguna valores en mi ejecución de procedimiento almacenado. Simplemente está consumiendo los valores que se le suministran.
DataTable dt = ...;
var query = session.CreateSqlQuery("EXEC foo_proc_here @data = :data")
.SetStructured("data", dt)
.ExecuteUpdate();
Desafortunadamente, esto arroja un mensaje "No se pudo ejecutar la consulta de manipulación masiva nativa". Las excepciones internas se quejan de errores de "Índice fuera de rango".
No estoy muy seguro de a dónde recurrir ahora, ya que el tema de los parámetros de tipos estructurados/valor de tabla con NHibernate parece lo suficientemente esotérico como para continuar terminando en esta misma publicación de Stack Overflow.
adjunte un generador de perfiles (nhProf por ejemplo) o servidor SQL y ver qué consulta se crea con su código. ¿Puedes publicar una excepción real? – IamDeveloper
Una solución más simple que la aceptada sería utilizar ADO.NET. NHibernate permite a los usuarios incluir IDbCommands
en las transacciones de NHibernate.
DataTable myIntsDataTable = new DataTable();
myIntsDataTable.Columns.Add("ID", typeof(int));
// ... Add rows to DataTable
ISession session = sessionFactory.GetSession();
using(ITransaction transaction = session.BeginTransaction())
{
IDbCommand command = new SqlCommand("StoredProcedureName");
command.Connection = session.Connection;
command.CommandType = CommandType.StoredProcedure;
var parameter = new SqlParameter();
parameter.ParameterName = "IntTable";
parameter.SqlDbType = SqlDbType.Structured;
parameter.Value = myIntsDataTable;
command.Parameters.Add(parameter);
session.Transaction.Enlist(command);
command.ExecuteNonQuery();
}
¿Podría adjuntar el 'parámetro' a' NHibernate.ISQLQuery', en lugar de usar ADO para toda la consulta? [Ref] (https://stackoverflow.com/q/46244598/241211) – Michael
- 1. ¿Es posible unirse a una función con valores de tabla y otra mesa con los parámetros
- 2. Parámetros con valores de tabla para procedimientos CLR en SQL Server 2008 - ¿es posible?
- 3. Pasar parámetros para ceder en Rails 3 (¿o es posible?)
- 4. ¿Cómo se pueden establecer los valores tipados de valores C# en NHibernate con los parámetros IQuery?
- 5. ¿Es posible pasar parámetros a una máscara?
- 6. Cómo invocar eficientemente parámetros con valores de tabla desde Ado.Net
- 7. ¿Cómo pasar todos los valores de la tabla en ssrs cuando no hay ningún valor en los parámetros?
- 8. Posible pasar parámetros a TestNG DataProvider?
- 9. ¿Es posible pasar valores de parámetro en Moq?
- 10. paso de parámetros Los parámetros con valores de tabla Vs Vs XML para SQL 2008 de aplicación .NET
- 11. Error de validación de parámetros. No es posible proporcionar valores válidos para todos los parámetros. (RsParameterError) de SQL Reporting 2008
- 12. ¿Cómo pasar valores (parámetros) entre páginas XAML?
- 13. ¿Es posible utilizar punteros de función en los procesos?
- 14. ¿Es posible obtener los valores de los parámetros para cada cuadro en la pila de llamadas en .NET
- 15. ¿Es posible utilizar la tabla cruzada/consulta dinámica en MySQL?
- 16. SQL Server CLR UDF con parámetros de salida: ¿es posible?
- 17. ¿Es posible pasar parámetros por referencia usando call_user_func_array()?
- 18. ¿Pasar parámetros con call_user_func?
- 19. Forzar gcc para pasar los parámetros en la pila
- 20. ¿Es posible verificar los valores en la compilación?
- 21. Pasar los parámetros a psql.exe
- 22. ¿Es posible omitir los parámetros que tienen valores predeterminados en una llamada de función php (5)?
- 23. Pregunta estadística en SQL: ¿esto es posible con NHibernate LINQ?
- 24. NHibernate - Force escaping en nombres de tabla
- 25. ¿Es posible utilizar Python con php
- 26. Uso de NHibernate con los parámetros de salida
- 27. ¿Es posible utilizar KVO en AVPlayerItem.loadedTimeRanges?
- 28. ¿Es posible transformar los tipos en un paquete de parámetros?
- 29. ¿Es posible tener validadores con parámetros?
- 30. ¿Es posible tener una llamada a un método dinámico para valores de parámetros predeterminados en Ruby?
No es una pregunta mala, pero ¿podría ampliar por qué quiere hacer esto? – Kendrick
¿Se puede usar SqlDBType.Structured para los parámetros de valores de tabla? –