En mi aplicación, necesito mostrar una lista de registros devueltos por diferentes procedimientos almacenados. Cada procedimiento de almacenamiento devuelve diferentes tipos de registros (es decir, el número de columnas y el tipo de columna son diferentes).Función C# para devolver objetos/entidades genéricos
Mi idea original era crear una clase para cada tipo de registros y crear una función que ejecutaría el procedimiento almacenado correspondiente y devolver la lista < MyCustomClass>. Algo como esto:
public class MyCustomClass1
{
public int Col1 { get; set; } //In reality the columns are NOT called Col1 and Col1 but have proper names
public int Col2 { get; set; }
}
public static List<MyCustomClass1> GetDataForReport1(int Param1)
{
List<MyCustomClass1> output = new List<MyCustomClass1>();
using (SqlConnection cn = new SqlConnection("MyConnectionString"))
using (SqlCommand cmd = new SqlCommand("MyProcNameForReport1", cn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@Param1", SqlDbType.Int).Value = Param1;
SqlDataReader rdr=cmd.ExecuteReader();
int Col1_Ordinal = rdr.GetOrdinal("Col1");
int Col2_Ordinal = rdr.GetOrdinal("Col2");
while (rdr.Read())
{
output.Add(new MyCustomClass1
{
Col1 = rdr.GetSqlInt32(Col1_Ordinal).Value,
Col2 = rdr.GetSqlInt32(Col2_Ordinal).Value
});
}
rdr.Close();
}
return output;
}
Esto funciona bien, pero como yo no necesito manipular esos registros en mi código de cliente (que sólo tiene que unirse a un control gráfico en mi capa de aplicación) que en realidad no tiene sentido hacerlo de esta manera, ya que terminaría con muchas clases personalizadas que realmente no usaría. He encontrado esto lo que hace el truco:
public static DataTable GetDataForReport1(int Param1)
{
DataTable output = new DataTable();
using (SqlConnection cn = new SqlConnection("MyConnectionString"))
using (SqlCommand cmd = new SqlCommand("MyProcNameForReport1", cn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@Param1", SqlDbType.Int).Value = Param1;
output.Load(cmd.ExecuteReader());
}
return output;
}
Esto devuelve un DataTable que puedo obligar a que sea el control que utilizo en mi capa de aplicación. Me pregunto si realmente se necesita el uso de una DataTable.
No podría devolver una lista de objetos creados desde clases anónimas:
public static List<object> GetDataForReport1(int Param1)
{
List<object> output = new List<object>();
using (SqlConnection cn = new SqlConnection("MyConnectionString"))
using (SqlCommand cmd = new SqlCommand("MyProcNameForReport1", cn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@Param1", SqlDbType.Int).Value = Param1;
SqlDataReader rdr=cmd.ExecuteReader();
int Col1_Ordinal = rdr.GetOrdinal("Col1");
int Col2_Ordinal = rdr.GetOrdinal("Col2");
while (rdr.Read())
{
output.Add(new
{
Col1 = rdr.GetSqlInt32(Col1_Ordinal).Value,
Col2 = rdr.GetSqlInt32(Col2_Ordinal).Value
});
}
rdr.Close();
}
return output;
}
alguna otra idea? Básicamente, solo quiero que la función devuelva 'algo' que puedo vincular a un control gráfico y prefiero no tener que crear clases personalizadas, ya que realmente no se usarían. ¿Cuál sería el mejor enfoque?
Por cierto, la mejor práctica para SqlDataReader es el siguiente estilo de uso: using (var rdr = cmd.ExecuteReader() {while (rdr.Read() {..}} - por lo que se cerrará (eliminará) automáticamente – abatishchev
Bien manchado. – Anthony