He leído muchas publicaciones sobre cómo insertar un DataTable en una tabla SQL, pero ¿hay una manera fácil de extraer una tabla SQL en un .NET DataTable?
Aquí, dale una oportunidad (esto es solo un pseudocódigo)
using System;
using System.Data;
using System.Data.SqlClient;
publicclassPullDataTest
{
// your data tableprivate DataTable dataTable = new DataTable();
publicPullDataTest()
{
}
// your method to pull data from database to datatable publicvoidPullData()
{
string connString = @"your connection string here";
string query = "select * from table";
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(query, conn);
conn.Open();
// create data adapter
SqlDataAdapter da = new SqlDataAdapter(cmd);
// this will query your database and return the result to your datatable
da.Fill(dataTable);
conn.Close();
da.Dispose();
}
}
El datatablecampo debe inicializarse antes de llamarda.Fill(dataTable)
Dabblernl
@ yonan2236 ¿Qué hay de tener un parámetro de salida de t sql al lado de la tabla de datos? ¿Cómo obtener el parámetro de salida también? ¿Es posible? ¿Muestra?
Ahmad Ebrahimi
1
Este código es propenso a errores y no se recomienda utilizar los recursos disponibles de esta manera. Consulte la respuesta de @Tim Rogers para conocer la solución limpia.
Xan-Kun Clark-Davis
Aparte de eso, eche un vistazo a LINQ (si aún no lo ha hecho), ya que realmente puede hacer algo de magia aquí :-)
Xan-Kun Clark-Davis
78
var table = new DataTable();
using (var da = new SqlDataAdapter("SELECT * FROM mytable", "connection string"))
{
da.Fill(table);
}
@ Xan-KunClark-Davis: el código en la respuesta aceptada filtra recursos si se lanza una excepción. Es posible que no desprecie usingtanto si comprende su equivalente completo.
Ben Voigt
@ Xan-KunClark-Davis ¿Por qué despreciarías Using?? Eso es como despreciar Witho Try-Catch. Yo soy al revés; Estoy decepcionado cuando no es apoyado por una clase.
SteveCinq
12
De muchas formas.
Use ADO.Net y use fill en el adaptador de datos para obtener un DataTable:
using (SqlDataAdapter dataAdapter
= new SqlDataAdapter ("SELECT blah FROM blahblah ", sqlConn))
{
// create the DataSet
DataSet dataSet = new DataSet();
// fill the DataSet using our DataAdapter
dataAdapter.Fill (dataSet);
}
Luego puede sacar la tabla de datos del conjunto de datos.
Tenga en cuenta que en el conjunto de datos de respuesta votada a favor no se usa (apareció después de mi respuesta)
// create data adapter
SqlDataAdapter da = new SqlDataAdapter(cmd);
// this will query your database and return the result to your datatable
da.Fill(dataTable);
Que es preferible al mío.
Sin embargo, recomendaría encarecidamente mirar el marco de la entidad ... usar tablas de datos y conjuntos de datos no es una gran idea. No hay seguridad de tipo en ellos, lo que significa que la depuración solo se puede realizar en tiempo de ejecución. Con colecciones fuertemente tipadas (que puede obtener usando LINQ2SQL o el marco de la entidad) su vida será mucho más fácil.
Editar: Quizás no estaba claro: tablas de datos = bueno, conjuntos de datos = malvado. Si está utilizando ADO.Net, puede utilizar ambas tecnologías (EF, linq2sql, dapper, nhibernate, orm of the month), ya que generalmente se encuentran en la parte superior de ado.net. La ventaja que obtiene es que puede actualizar su modelo mucho más fácilmente a medida que cambia su esquema, siempre que tenga el nivel correcto de abstracción mediante la generación de código.
El adaptador ado.net utiliza proveedores que exponen la información de tipo de la base de datos, por ejemplo, de forma predeterminada, utiliza un proveedor de servidor SQL, también puede conectar, por ejemplo, el proveedor de postgress devart y seguir teniendo acceso a la información de tipo que luego le permite utilizar el formato de su elección como se indicó anteriormente (casi sin dolor, hay algunas peculiaridades); creo que Microsoft también proporciona un proveedor de Oracle. El propósito COMPLETO de esto es abstraerse de la implementación de la base de datos cuando sea posible.
Los conjuntos de datos con tipo tienen seguridad de tipos y colecciones fuertemente tipadas, al igual que EF. Pero esos son solo para cuando su aplicación está estrechamente acoplada a la base de datos. Si está escribiendo una herramienta que tiene que funcionar con muchas bases de datos diferentes, la seguridad de tipos es un deseo desesperado.
Ross Presser
1
Los conjuntos de datos escritos en .net son una creación horrible de locura y aflicción xml. Nunca he trabajado en un lugar que esté dispuesto a aceptar la sobrecarga de mantener todo eso para conjuntos de datos mecanografiados microsoft. No creo que ni siquiera Microsoft sugiera que sea sensato en estos días. En cuanto a la seguridad de tipos con múltiples bases de datos, por supuesto, puede obtenerla; el punto es que la convierta en una colección escrita lo antes posible y la transmita para restringir los problemas de tipos a un lugar específico. Orms ayudará con eso y funcionará perfectamente bien con múltiples bases de datos. Si no te gusta EF, usa algo más ligero como apuesto.
John Nicholas
1
No me entendiste. Si está escribiendo una herramienta de propósito general que no tiene idea de a qué tipo de base de datos se va a conectar, entonces la seguridad de tipos es un deseo desesperado.
Ross Presser
1
Se da sql. Además, si no sabe qué tipo de base de datos, ¿por qué tiene que ser una base de datos? ¿Cuál sería la aplicación de una herramienta tan genérica? Si alguna vez necesita conectarse a bases de datos que son realmente tan radicalmente diferentes, se desviaría de ellas detrás de un patrón de repositorio y luego, dentro de eso, necesitaría diferentes adaptadores de bases de datos especializados y en ese momento sabría los detalles. El hecho es que el código de consumo tiene expectativas de tipo -> afirmaciones de tipo en el adaptador. Su restricción significa que no tiene idea sobre el lenguaje de la base de datos y, por lo tanto, no puede realizar consultas.
John Nicholas
3
Suponga que está escribiendo un clon de SSMS.
Ross Presser
9
Versión independiente del proveedor, se basa únicamente en interfaces ADO.NET; 2 maneras:
public DataTable Read1<T>(string query) where T : IDbConnection, new()
{
using (var conn = new T())
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = query;
cmd.Connection.ConnectionString = _connectionString;
cmd.Connection.Open();
var table = new DataTable();
table.Load(cmd.ExecuteReader());
return table;
}
}
}
public DataTable Read2<S, T>(string query) where S : IDbConnection, new()
where T : IDbDataAdapter, IDisposable, new()
{
using (var conn = new S())
{
using (var da = new T())
{
using (da.SelectCommand = conn.CreateCommand())
{
da.SelectCommand.CommandText = query;
da.SelectCommand.Connection.ConnectionString = _connectionString;
DataSet ds = new DataSet(); //conn is opened by dataadapter
da.Fill(ds);
return ds.Tables[0];
}
}
}
}
Hice algunas pruebas de rendimiento y el segundo enfoque siempre superó al primero.
Read1se ve mejor a los ojos, pero el adaptador de datos funciona mejor (no confundir que un db superó al otro, las consultas fueron todas diferentes). Sin embargo, la diferencia entre los dos dependía de la consulta. La razón podría ser que Loadrequiere que se verifiquen varias restricciones fila por fila de la documentación al agregar filas (es un método activado DataTable) mientras Fillestá en DataAdapters que fueron diseñados solo para eso: creación rápida de DataTables.
Necesita rodear el DataTable.Load()con .BeginLoadData()y .EndLoadData()para lograr la misma velocidad que con el DataSet.
Nikola Bogdanović
1
Modelo centrado: ¡puedes usarlo desde cualquier lugar!
Solo necesita llamar al formato de abajo desde su función a esta clase
DataSet ds = new DataSet();
SqlParameter[] p = new SqlParameter[1];
string Query = "Describe Query Information/either sp, text or TableDirect";
DbConnectionHelper dbh = new DbConnectionHelper ();
ds = dbh. DBConnection("Here you use your Table Name", p , string Query, CommandType.StoredProcedure);
Eso es. es un método perfecto.
publicclassDbConnectionHelper {
public DataSet DBConnection(string TableName, SqlParameter[] p, string Query, CommandType cmdText) {
string connString = @ "your connection string here";
//Object Declaration
DataSet ds = new DataSet();
SqlConnection con = new SqlConnection();
SqlCommand cmd = new SqlCommand();
SqlDataAdapter sda = new SqlDataAdapter();
try {
//Get Connection string and Make Connection
con.ConnectionString = connString; //Get the Connection Stringif (con.State == ConnectionState.Closed) {
con.Open(); //Connection Open
}
if (cmdText == CommandType.StoredProcedure) //Type : Stored Procedure
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = Query;
if (p.Length > 0) // If Any parameter is there means, we need to add.
{
for (int i = 0; i < p.Length; i++) {
cmd.Parameters.Add(p[i]);
}
}
}
if (cmdText == CommandType.Text) // Type : Text
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = Query;
}
if (cmdText == CommandType.TableDirect) //Type: Table Direct
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = Query;
}
cmd.Connection = con; //Get Connection in Command
sda.SelectCommand = cmd; // Select Command From Command to SqlDataAdaptor
sda.Fill(ds, TableName); // Execute Query and Get Result into DataSet
con.Close(); //Connection Close
} catch (Exception ex) {
throw ex; //Here you need to handle Exception
}
return ds;
}
}
Respuestas:
Aquí, dale una oportunidad (esto es solo un pseudocódigo)
using System; using System.Data; using System.Data.SqlClient; public class PullDataTest { // your data table private DataTable dataTable = new DataTable(); public PullDataTest() { } // your method to pull data from database to datatable public void PullData() { string connString = @"your connection string here"; string query = "select * from table"; SqlConnection conn = new SqlConnection(connString); SqlCommand cmd = new SqlCommand(query, conn); conn.Open(); // create data adapter SqlDataAdapter da = new SqlDataAdapter(cmd); // this will query your database and return the result to your datatable da.Fill(dataTable); conn.Close(); da.Dispose(); } }
fuente
datatable
campo debe inicializarse antes de llamarda.Fill(dataTable)
var table = new DataTable(); using (var da = new SqlDataAdapter("SELECT * FROM mytable", "connection string")) { da.Fill(table); }
fuente
using
tanto si comprende su equivalente completo.Using
?? Eso es como despreciarWith
oTry-Catch
. Yo soy al revés; Estoy decepcionado cuando no es apoyado por una clase.De muchas formas.
Use ADO.Net y use fill en el adaptador de datos para obtener un DataTable:
using (SqlDataAdapter dataAdapter = new SqlDataAdapter ("SELECT blah FROM blahblah ", sqlConn)) { // create the DataSet DataSet dataSet = new DataSet(); // fill the DataSet using our DataAdapter dataAdapter.Fill (dataSet); }
Luego puede sacar la tabla de datos del conjunto de datos.
Tenga en cuenta que en el conjunto de datos de respuesta votada a favor no se usa (apareció después de mi respuesta)
// create data adapter SqlDataAdapter da = new SqlDataAdapter(cmd); // this will query your database and return the result to your datatable da.Fill(dataTable);
Que es preferible al mío.
Sin embargo, recomendaría encarecidamente mirar el marco de la entidad ... usar tablas de datos y conjuntos de datos no es una gran idea. No hay seguridad de tipo en ellos, lo que significa que la depuración solo se puede realizar en tiempo de ejecución. Con colecciones fuertemente tipadas (que puede obtener usando LINQ2SQL o el marco de la entidad) su vida será mucho más fácil.
Editar: Quizás no estaba claro: tablas de datos = bueno, conjuntos de datos = malvado. Si está utilizando ADO.Net, puede utilizar ambas tecnologías (EF, linq2sql, dapper, nhibernate, orm of the month), ya que generalmente se encuentran en la parte superior de ado.net. La ventaja que obtiene es que puede actualizar su modelo mucho más fácilmente a medida que cambia su esquema, siempre que tenga el nivel correcto de abstracción mediante la generación de código.
El adaptador ado.net utiliza proveedores que exponen la información de tipo de la base de datos, por ejemplo, de forma predeterminada, utiliza un proveedor de servidor SQL, también puede conectar, por ejemplo, el proveedor de postgress devart y seguir teniendo acceso a la información de tipo que luego le permite utilizar el formato de su elección como se indicó anteriormente (casi sin dolor, hay algunas peculiaridades); creo que Microsoft también proporciona un proveedor de Oracle. El propósito COMPLETO de esto es abstraerse de la implementación de la base de datos cuando sea posible.
fuente
Versión independiente del proveedor, se basa únicamente en interfaces ADO.NET; 2 maneras:
public DataTable Read1<T>(string query) where T : IDbConnection, new() { using (var conn = new T()) { using (var cmd = conn.CreateCommand()) { cmd.CommandText = query; cmd.Connection.ConnectionString = _connectionString; cmd.Connection.Open(); var table = new DataTable(); table.Load(cmd.ExecuteReader()); return table; } } } public DataTable Read2<S, T>(string query) where S : IDbConnection, new() where T : IDbDataAdapter, IDisposable, new() { using (var conn = new S()) { using (var da = new T()) { using (da.SelectCommand = conn.CreateCommand()) { da.SelectCommand.CommandText = query; da.SelectCommand.Connection.ConnectionString = _connectionString; DataSet ds = new DataSet(); //conn is opened by dataadapter da.Fill(ds); return ds.Tables[0]; } } } }
Hice algunas pruebas de rendimiento y el segundo enfoque siempre superó al primero.
Stopwatch sw = Stopwatch.StartNew(); DataTable dt = null; for (int i = 0; i < 100; i++) { dt = Read1<MySqlConnection>(query); // ~9800ms dt = Read2<MySqlConnection, MySqlDataAdapter>(query); // ~2300ms dt = Read1<SQLiteConnection>(query); // ~4000ms dt = Read2<SQLiteConnection, SQLiteDataAdapter>(query); // ~2000ms dt = Read1<SqlCeConnection>(query); // ~5700ms dt = Read2<SqlCeConnection, SqlCeDataAdapter>(query); // ~5700ms dt = Read1<SqlConnection>(query); // ~850ms dt = Read2<SqlConnection, SqlDataAdapter>(query); // ~600ms dt = Read1<VistaDBConnection>(query); // ~3900ms dt = Read2<VistaDBConnection, VistaDBDataAdapter>(query); // ~3700ms } sw.Stop(); MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString());
Read1
se ve mejor a los ojos, pero el adaptador de datos funciona mejor (no confundir que un db superó al otro, las consultas fueron todas diferentes). Sin embargo, la diferencia entre los dos dependía de la consulta. La razón podría ser queLoad
requiere que se verifiquen varias restricciones fila por fila de la documentación al agregar filas (es un método activadoDataTable
) mientrasFill
está en DataAdapters que fueron diseñados solo para eso: creación rápida de DataTables.fuente
DataTable.Load()
con.BeginLoadData()
y.EndLoadData()
para lograr la misma velocidad que con elDataSet
.Modelo centrado: ¡puedes usarlo desde cualquier lugar!
Solo necesita llamar al formato de abajo desde su función a esta clase
DataSet ds = new DataSet(); SqlParameter[] p = new SqlParameter[1]; string Query = "Describe Query Information/either sp, text or TableDirect"; DbConnectionHelper dbh = new DbConnectionHelper (); ds = dbh. DBConnection("Here you use your Table Name", p , string Query, CommandType.StoredProcedure);
Eso es. es un método perfecto.
public class DbConnectionHelper { public DataSet DBConnection(string TableName, SqlParameter[] p, string Query, CommandType cmdText) { string connString = @ "your connection string here"; //Object Declaration DataSet ds = new DataSet(); SqlConnection con = new SqlConnection(); SqlCommand cmd = new SqlCommand(); SqlDataAdapter sda = new SqlDataAdapter(); try { //Get Connection string and Make Connection con.ConnectionString = connString; //Get the Connection String if (con.State == ConnectionState.Closed) { con.Open(); //Connection Open } if (cmdText == CommandType.StoredProcedure) //Type : Stored Procedure { cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = Query; if (p.Length > 0) // If Any parameter is there means, we need to add. { for (int i = 0; i < p.Length; i++) { cmd.Parameters.Add(p[i]); } } } if (cmdText == CommandType.Text) // Type : Text { cmd.CommandType = CommandType.Text; cmd.CommandText = Query; } if (cmdText == CommandType.TableDirect) //Type: Table Direct { cmd.CommandType = CommandType.Text; cmd.CommandText = Query; } cmd.Connection = con; //Get Connection in Command sda.SelectCommand = cmd; // Select Command From Command to SqlDataAdaptor sda.Fill(ds, TableName); // Execute Query and Get Result into DataSet con.Close(); //Connection Close } catch (Exception ex) { throw ex; //Here you need to handle Exception } return ds; } }
fuente