Leer la tabla SQL en C # DataTable

Respuestas:

156

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();
    }
}
yonan2236
fuente
18
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);
}
Tim Rogers
fuente
7
@ 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.

John Nicholas
fuente
1
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.

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());

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.

nawfal
fuente
3
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.

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;
   }
  }
Elango Sengottaiyan
fuente