Estoy haciendo algo básico en C # (MS VS2008) y tengo una pregunta más sobre el diseño adecuado que sobre el código específico.
Estoy creando una tabla de datos y luego intento cargar la tabla de datos desde un lector de datos (que se basa en un procedimiento almacenado de SQL). Lo que me pregunto es si la forma más eficiente de cargar la tabla de datos es hacer una declaración while, o si hay una forma mejor.
Para mí, el único inconveniente es que tengo que escribir manualmente los campos que quiero agregar en mi declaración while, pero tampoco conozco la forma de automatizar eso de todos modos, ya que no quiero todos los campos del SP, solo seleccione unos , pero eso no es gran cosa en mi opinión.
He incluido fragmentos de código debajo de la totalidad de lo que hago, aunque para mí el código en sí no es notable o incluso lo que estoy preguntando. Además, preguntándome sobre mi metodología, pediré ayuda con el código más adelante si mi estrategia es incorrecta / ineficiente.
var dtWriteoffUpload = new DataTable();
dtWriteoffUpload.Columns.Add("Unit");
dtWriteoffUpload.Columns.Add("Year");
dtWriteoffUpload.Columns.Add("Period");
dtWriteoffUpload.Columns.Add("Acct");
dtWriteoffUpload.Columns.Add("Descr");
dtWriteoffUpload.Columns.Add("DEFERRAL_TYPE");
dtWriteoffUpload.Columns.Add("NDC_Indicator");
dtWriteoffUpload.Columns.Add("Mgmt Cd");
dtWriteoffUpload.Columns.Add("Prod");
dtWriteoffUpload.Columns.Add("Node");
dtWriteoffUpload.Columns.Add("Curve_Family");
dtWriteoffUpload.Columns.Add("Sum Amount");
dtWriteoffUpload.Columns.Add("Base Curr");
dtWriteoffUpload.Columns.Add("Ledger");
cmd = util.SqlConn.CreateCommand();
cmd.CommandTimeout = 1000;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "proc_writeoff_data_details";
cmd.Parameters.Add("@whoAmI", SqlDbType.VarChar).Value =
WindowsIdentity.GetCurrent().Name;
cmd.Parameters.Add("@parmEndDateKey", SqlDbType.VarChar).Value = myMostRecentActualDate;
cmd.Parameters.Add("@countrykeys", SqlDbType.VarChar).Value = myCountryKey;
cmd.Parameters.Add("@nodekeys", SqlDbType.VarChar).Value = "1,2";
break;
dr = cmd.ExecuteReader();
while (dr.Read())
{
dtWriteoffUpload.Rows.Add(dr["country name"].ToString(), dr["country key"].ToString());
}
Respuestas:
Puede cargar un archivo
DataTable
directamente desde un lector de datos utilizando elLoad()
método que acepta un archivoIDataReader
.fuente
Comprueba el siguiente código. Automáticamente se convertirá como DataTable
fuente
dt.Load(reader)
Tampoco siempre funciona: obtendría esos molestosObject reference not set to an instance of an object
errores, probablemente cuando no obtengo ninguna fila. Algo manual como este es útil. Lo probé y tuve que deshacerme de esascolumn.
líneas en eldtSchema
foreach
bucle porque decía que era un lanzamiento ilegal parabool
en(bool)drow["IsUnique"]
. No los necesitaba, obtener los nombres de las columnas para completar la nuevaDataTable
es suficiente. Esto me ayudó a superar unds.Fill(adapter)
problema en el que no podía cargar una tabla grande conSELECT * FROM MyTable
.if (!dr.IsDBNull(i))
como lo siguiente dentro de esefor
bucle. Luego haces tusdataRow
cosas. Pero luego necesitas unaelse
sobre eso, en caso de que encuentres un nulo. Si lo hace, debe averiguar el tipo de columna que está agregando y asignar el nulo en consecuencia (es decir, puede asignarString.Empty
si es de tipoSystem.String
, pero debe asignar0
si esSystem.Int16
(campo booleano) oSystem.Decimal
.Si está intentando cargar un
DataTable
, aproveche elSqlDataAdapter
en su lugar:Ni siquiera necesita definir las columnas. Simplemente crea el
DataTable
yFill
eso.Aquí
cString
está su cadena de conexión ysql
el comando del procedimiento almacenado.fuente
SqlDataReader
leerlos usando un bucle a través de los campos.Como dijo Sagi en su respuesta, DataTable.Load es una buena solución. Si está intentando cargar varias tablas desde un solo lector, no necesita llamar a DataReader.NextResult. El método DataTable.Load también avanza al lector al siguiente conjunto de resultados (si lo hubiera).
fuente
También miré en esto, y después de comparar el método SqlDataAdapter.Fill con las funciones SqlDataReader.Load, descubrí que el método SqlDataAdapter.Fill es más del doble de rápido con los conjuntos de resultados que he estado usando
Código utilizado:
Resultados:
Para problemas de rendimiento, usar el método SqlDataAdapter.Fill es mucho más eficiente. Entonces, a menos que quieras dispararte en el pie, usa eso. Funciona más rápido para conjuntos de datos grandes y pequeños.
fuente