2010-04-30 19 views
9

Tengo un par de procedimientos almacenados en T-SQL donde cada procedimiento almacenado tiene un esquema fijo para el conjunto de resultados.Obtención del esquema .NET para un resultado de procedimiento almacenado

Necesito asignar los conjuntos de resultados para cada procedimiento a un objeto POCO y necesito el nombre y el tipo de columna para cada columna en el conjunto de resultados. ¿Hay una manera rápida de acceder a la información?

La mejor forma que he encontrado hasta ahora es acceder a cada procedimiento almacenado desde .NET y escribir mi propio método de extensión en un IDataReader/IDataRecord para eliminar la información (nombres y tipos de columnas).

ejemplo, un procedimiento almacenado ejecutando la siguiente consulta:

SELECT Id, IntField, NullableIntField, VarcharField, DateField FROM SomeTable 

me requeriría tener la información de asignación:

Id - Guid 
IntField - System.Int32 
NullableIntField - Nullable<System.Int32> 
VarcharField - String 
DateField - DateTime 

Respuesta

10

Creo que debería poder utilizar SqlDataReader.GetSchemaTable método para acceder al esquema.

Más información se puede encontrar aquí.

http://support.microsoft.com/kb/310107

Ejemplo de lo alto fuente

SqlConnection cn = new SqlConnection(); 
SqlCommand cmd = new SqlCommand(); 
DataTable schemaTable; 
SqlDataReader myReader; 

//Open a connection to the SQL Server Northwind database. 
cn.ConnectionString = "Data Source=server;User ID=login; 
         Password=password;Initial Catalog=DB"; 
cn.Open(); 

//Retrieve records from the Employees table into a DataReader. 
cmd.Connection = cn; 
cmd.CommandText = "SELECT Id, IntField, NullableIntField, VarcharField, DateField FROM SomeTable"; 

myReader = cmd.ExecuteReader(CommandBehavior.KeyInfo); 

//Retrieve column schema into a DataTable. 
schemaTable = myReader.GetSchemaTable(); 

//For each field in the table... 
foreach (DataRow myField in schemaTable.Rows){ 
    //For each property of the field... 
    foreach (DataColumn myProperty in schemaTable.Columns) { 
    //Display the field name and value. 
    Console.WriteLine(myProperty.ColumnName + " = " + myField[myProperty].ToString()); 
    } 
    Console.WriteLine(); 

    //Pause. 
    Console.ReadLine(); 
} 

//Always close the DataReader and connection. 
myReader.Close(); 
cn.Close(); 
+0

Sí, así es como planeé extraer la información en mi método de extensión. Gracias por la sugerencia – PHeiberg

1

creo que lo que está haciendo es probablemente el mejor enfoque. No hay un repositorio mágico que contenga toda esa información, realmente. Puede obtener información acerca de los parámetros de proceso almacenados desde las vistas del catálogo del sistema, pero los nombres y tipos de forma y campo del conjunto de resultados no se almacenan en ninguna parte de las vistas del sistema de SQL Server, desafortunadamente.

+0

Gracias por la confirmación de mi teoría. – PHeiberg

0

si esto es una cosa de tiempo que tiene que hacer, y no es algo que va a hacer en tiempo de ejecución cada vez que el procedimiento se denomina, a continuación, sólo modificar el resultado de la consulta establecido para volcar las filas en una tabla nueva utilizando INTO ThrowArayTable:

SELECT 
    Col1, col2, col3, ... 
    INTO ThrowArayTable  ----<<<add this line to existing result set query 
    FROM ... 
    WHERE ... 

Ejecutar la aplicación o llamar al procedur e manualmente para generar ThrowArayTable. Ahora puede buscar los tipos de datos y columnas de la columna usando cualquier método, SSMS o INFORMATION_SCHEMA.COLUMNS

Simplemente recuerde cambiar el procedimiento de regreso (elimine el valor INTO ThrowArayTable) para que realmente devuelva el conjunto de resultados.

+0

Sí, buena sugerencia. No conocía ese método para acceder a la información de tipo. Las desventajas son que no tengo acceso a la edición de los procedimientos almacenados, ya que no están bajo mi control. También tendría que asignar los tipos de columnas manualmente a los tipos .NET correspondientes, incluidos los tipos que aceptan valores nulos. – PHeiberg

+1

Gracias. A veces, el enfoque más simple es el mejor. Esto es exactamente lo que quería. No sé por qué la solución me eludió. Supongo que porque estaba pensando en el contexto de un procedimiento almacenado. –

1

Otra opción (podría ser mejor o peor que GetSchemaTable() dependiendo de sus necesidades).
El siguiente código le da un DataTable con la estructura de la columna idéntica a su conjunto de resultados:

DataTable table = new DataTable(); 
var cmd = new SqlCommand("..."); 
using (var reader = cmd.Execute(CommandBehaviour.SchemaOnly)) 
    table.Load(reader); 
+0

Esto usa SET FMTONLY ON, que está en desuso (desde 2012 ??). Ver mi respuesta arriba. –

+0

Diría que le corresponde a MS cambiar la implementación de Execute (CommandBehavior.SchemaOnly) en consecuencia. – VladV

Cuestiones relacionadas