Leggi la tabella SQL in C # DataTable


Risposte:


156

Ecco, prova a farlo (questo è solo uno pseudocodice)

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

18
Il datatablecampo deve essere inizializzato prima di chiamareda.Fill(dataTable)
Dabblernl

@ yonan2236 Che ne dici di avere il parametro di output da t sql accanto a datatable? come ottenere anche i parametri di output? È possibile? Campione?
Ahmad Ebrahimi

1
Questo codice è soggetto a errori e non è consigliabile utilizzare le risorse disponibili in questo modo. Si prega di consultare la risposta di @Tim Rogers per la soluzione pulita.
Xan-Kun Clark-Davis

A parte questo, dai un'occhiata a LINQ (se non l'hai già fatto) in quanto può davvero fare un po 'di magia qui :-)
Xan-Kun Clark-Davis

78
var table = new DataTable();    
using (var da = new SqlDataAdapter("SELECT * FROM mytable", "connection string"))
{      
    da.Fill(table);
}

7
@ Xan-KunClark-Davis: il codice nella risposta accettata perde risorse se viene generata un'eccezione. Potresti non disprezzare usingcosì tanto se capissi il suo completo equivalente.
Ben Voigt

@ Xan-KunClark-Davis Perché disprezzeresti Using?? È come disprezzare Witho Try-Catch. Io sono il contrario; Sono deluso quando non è supportato da una classe.
SteveCinq

12

Molti modi.

Usa ADO.Net e usa fill sull'adattatore dati per ottenere una 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);
}

È quindi possibile estrarre la tabella dati dal set di dati.

Nota nel set di dati della risposta con voto positivo non viene utilizzato, (è apparso dopo la mia risposta)

// create data adapter
SqlDataAdapter da = new SqlDataAdapter(cmd);
// this will query your database and return the result to your datatable
da.Fill(dataTable);

Che è preferibile al mio.

Consiglio vivamente di guardare al framework di entità ... l'utilizzo di datatables e set di dati non è una grande idea. Non esiste alcuna protezione dai tipi su di essi, il che significa che il debug può essere eseguito solo in fase di esecuzione. Con raccolte fortemente tipizzate (che puoi ottenere usando LINQ2SQL o il framework di entità) la tua vita sarà molto più semplice.

Modifica: forse non ero chiaro: datatables = buono, dataset = male. Se stai utilizzando ADO.Net, puoi utilizzare entrambe queste tecnologie (EF, linq2sql, dapper, nhibernate, orm of the month) poiché generalmente si trovano sopra ado.net. Il vantaggio che ottieni è che puoi aggiornare il tuo modello molto più facilmente man mano che lo schema cambia, a condizione che tu abbia il giusto livello di astrazione facendo leva sulla generazione del codice.

L'adattatore ado.net utilizza provider che espongono le informazioni sul tipo del database, ad esempio per impostazione predefinita utilizza un provider di server sql, puoi anche collegare, ad esempio, il provider postgress devart e ottenere comunque l'accesso alle informazioni sul tipo che verranno poi ti permettono di usare come sopra il tuo orm di scelta (quasi indolore - ci sono alcune stranezze) - credo che Microsoft fornisca anche un provider Oracle. L'INTERO scopo di questo è astrarre dall'implementazione del database ove possibile.


1
I set di dati tipizzati hanno l'indipendenza dai tipi e raccolte fortemente tipizzate, proprio come EF. Ma quelli sono solo per quando la tua app è strettamente collegata al database. Se stai scrivendo uno strumento che deve funzionare con molti database diversi, la protezione dai tipi è un desiderio senza speranza.
Ross Presser

1
I set di dati digitati in .net sono un'orribile creazione di follia e guai xml. Non ho mai lavorato in un posto che è disposto ad accettare il sovraccarico di mantenere tutto ciò per un set di dati tipizzato da Microsoft. Non credo che nemmeno Microsoft suggerisca che sia sensato in questi giorni. Per quanto riguarda l'indipendenza dai tipi con più database, ovviamente puoi ottenerlo: il punto è che lo converti in una raccolta digitata al più presto e lo passi in modo da limitare i problemi di tipo a un luogo specifico. Orms ti aiuterà in questo e funzionerà perfettamente con più database. Se non ti piace EF usa qualcosa di più leggero come dapper.
John Nicholas

1
Non mi hai capito. Se stai scrivendo uno strumento generico che non ha idea del tipo di database a cui si connetterà, l'indipendenza dai tipi è un desiderio senza speranza.
Ross Presser

1
Sql è dato. Inoltre, se non sai che tipo di database, perché deve essere un database? Quale sarebbe l'applicazione di uno strumento così generico? Se dovessi mai aver bisogno di connetterti a database che sono davvero così radicalmente diversi, ti asterresti da esso dietro un modello di repository e quindi al suo interno avresti bisogno di adattatori di database specializzati diversi ea quel punto sapresti le specifiche. Il fatto sta consumando codice ha aspettative di tipo -> asserzioni di tipo nell'adattatore. Il tuo vincolo significa che non hai idea del linguaggio del database e quindi non puoi eseguire query.
John Nicholas

3
Supponi di scrivere un clone di SSMS?
Ross Presser

9

Versione indipendente dal fornitore, si basa esclusivamente sulle interfacce ADO.NET; 2 modi:

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];
            }
        }
    }
}

Ho eseguito alcuni test delle prestazioni e il secondo approccio ha sempre sovraperformato il primo.

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

Read1ha un aspetto migliore agli occhi, ma l'adattatore dati funziona meglio (per non confondere che un db ha superato l'altro, le query erano tutte diverse). La differenza tra i due dipendeva però dalla query. Il motivo potrebbe essere che Loadrichiede che vari vincoli vengano controllati riga per riga dalla documentazione quando si aggiungono righe (è un metodo attivo DataTable) mentre Fillè su DataAdapters che sono stati progettati proprio per questo: creazione rapida di DataTable.


3
È necessario circondare il DataTable.Load()con .BeginLoadData()e .EndLoadData()per ottenere la stessa velocità di DataSet.
Nikola Bogdanović

1

Modello centrato: puoi usarlo da qualsiasi luogo!

Hai solo bisogno di chiamare Below Format dalla tua funzione a questa classe

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

Questo è tutto. è un metodo perfetto.

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;
   }
  }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.