Lesen Sie die SQL-Tabelle in C # DataTable

89

Ich habe viele Beiträge zum Einfügen einer DataTable in eine SQL-Tabelle gelesen. Gibt es jedoch eine einfache Möglichkeit, eine SQL-Tabelle in eine .NET DataTable zu ziehen?

Wille
quelle
8
Umm ... die Fill-Methode für einen DataAdapter verwenden?
John Bledsoe

Antworten:

152

Probieren Sie es hier aus (dies ist nur ein Pseudocode)

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
quelle
16
Das datatableFeld muss vor dem Aufruf initialisiert werdenda.Fill(dataTable)
Dabblernl
@ yonan2236 Was ist mit dem Ausgabeparameter von t sql neben datatable? Wie bekomme ich auch Ausgabeparameter? Ist es möglich? Stichprobe?
Ahmad Ebrahimi
1
Dieser Code ist fehleranfällig und es wird nicht empfohlen, die verfügbaren Ressourcen auf diese Weise zu verwenden. Die saubere Lösung finden Sie in der Antwort von @Tim Rogers.
Xan-Kun Clark-Davis
Abgesehen davon, schauen Sie sich LINQ an (falls noch nicht geschehen), da es hier wirklich etwas zaubern kann :-)
Xan-Kun Clark-Davis
77
var table = new DataTable();    
using (var da = new SqlDataAdapter("SELECT * FROM mytable", "connection string"))
{      
    da.Fill(table);
}
Tim Rogers
quelle
7
@ Xan-KunClark-Davis: Der Code in der akzeptierten Antwort verliert Ressourcen, wenn eine Ausnahme ausgelöst wird. Sie könnten nicht usingso sehr verachten , wenn Sie das vollständige Äquivalent verstanden hätten.
Ben Voigt
@ Xan-KunClark-Davis Warum würdest du verachten Using? Das ist wie Verachtung Withoder Try-Catch. Ich bin das Gegenteil; Ich bin enttäuscht, wenn es nicht von einer Klasse unterstützt wird.
SteveCinq
11

Viele Möglichkeiten.

Verwenden Sie ADO.Net und verwenden Sie fill auf dem Datenadapter, um eine Datentabelle zu erhalten:

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

Sie können dann die Datentabelle aus dem Datensatz abrufen.

Hinweis im aktualisierten Antwortdatensatz wird nicht verwendet (erscheint nach meiner Antwort)

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

Welches ist mir vorzuziehen.

Ich würde jedoch dringend empfehlen, sich das Entity Framework anzusehen ... die Verwendung von Datentabellen und Datasets ist keine gute Idee. Es gibt keine Typensicherheit, was bedeutet, dass das Debuggen nur zur Laufzeit durchgeführt werden kann. Mit stark typisierten Sammlungen (die Sie mit LINQ2SQL oder dem Entity Framework erhalten können) wird Ihr Leben viel einfacher.

Edit: Vielleicht war mir nicht klar: Datatables = gut, Datasets = böse. Wenn Sie ADO.Net verwenden, können Sie beide Technologien (EF, linq2sql, dapper, nhibernate oder orm des Monats) verwenden, da sie sich normalerweise auf ado.net befinden. Der Vorteil, den Sie erhalten, besteht darin, dass Sie Ihr Modell viel einfacher aktualisieren können, wenn sich Ihr Schema ändert, vorausgesetzt, Sie verfügen über die richtige Abstraktionsebene, indem Sie die Codegenerierung nutzen.

Der ado.net-Adapter verwendet Anbieter, die die Typinformationen der Datenbank verfügbar machen. Standardmäßig wird beispielsweise ein SQL Server-Anbieter verwendet. Sie können beispielsweise auch den devart postgress-Anbieter anschließen und trotzdem auf die Typinformationen zugreifen, die dann angezeigt werden Erlauben Sie Ihnen, wie oben beschrieben Ihren Orm Ihrer Wahl zu verwenden (fast schmerzlos - es gibt ein paar Macken) - ich glaube, Microsoft bietet auch einen Orakel-Anbieter an. Der GESAMTE Zweck ist es, wenn möglich von der Datenbankimplementierung abzuweichen.

John Nicholas
quelle
1
Typisierte Datensätze verfügen wie EF über Typensicherheit und stark typisierte Sammlungen. Dies gilt jedoch nur, wenn Ihre App eng mit der Datenbank verbunden ist. Wenn Sie ein Tool schreiben, das mit vielen verschiedenen Datenbanken arbeiten muss, ist die Typensicherheit ein hoffnungsloser Wunsch.
Ross Presser
1
Typisierte Datensätze in .net sind eine schreckliche Kreation von XML-Wahnsinn und Leid. Ich habe noch nie an einem Ort gearbeitet, der bereit ist, den Aufwand für die Verwaltung all dessen für Datensätze mit Microsoft-Typ-Typ zu akzeptieren. Ich denke nicht einmal, dass Microsoft dies heutzutage für sinnvoll hält. Was die Typensicherheit mit mehreren Datenbanken betrifft, können Sie sie natürlich erhalten - der Punkt ist, dass Sie sie so schnell wie möglich in eine typisierte Sammlung konvertieren und diese weitergeben, damit Sie die Typprobleme auf einen bestimmten Ort beschränken. Orms hilft dabei und funktioniert perfekt mit mehreren Datenbanken. Wenn Sie EF nicht mögen, verwenden Sie etwas Leichteres wie Dapper.
John Nicholas
1
Du hast mich nicht verstanden. Wenn Sie ein Allzweck-Tool schreiben, das keine Ahnung hat, mit welcher Art von Datenbank eine Verbindung hergestellt werden soll, ist die Typensicherheit ein hoffnungsloser Wunsch.
Ross Presser
1
SQL ist gegeben. Außerdem, wenn Sie nicht wissen, welche Art von Datenbank, warum muss es dann überhaupt eine Datenbank sein? Was wäre die Anwendung eines solchen generischen Tools? Wenn Sie jemals eine Verbindung zu Datenbanken herstellen müssen, die wirklich so radikal anders sind, würden Sie hinter einem Repository-Muster davon abstrahieren, und innerhalb dieses würden Sie verschiedene spezialisierte Datenbankadapter benötigen, und an diesem Punkt würden Sie die Einzelheiten kennen. Die Tatsache, dass Code verbraucht wird, hat Typerwartungen -> Typzusicherungen im Adapter. Ihre Einschränkung bedeutet, dass Sie keine Ahnung von der Datenbanksprache haben und daher keine Abfragen durchführen können.
John Nicholas
3
Angenommen, Sie haben einen SSMS-Klon geschrieben?
Ross Presser
9

Die herstellerunabhängige Version basiert ausschließlich auf ADO.NET-Schnittstellen. 2 Wege:

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

Ich habe einige Leistungstests durchgeführt, und der zweite Ansatz hat den ersten immer übertroffen.

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

Read1sieht auf den Augen besser aus, aber der Datenadapter funktioniert besser (nicht zu verwechseln, dass eine Datenbank die andere übertrifft, die Abfragen waren alle unterschiedlich). Der Unterschied zwischen den beiden hing jedoch von der Abfrage ab. Der Grund könnte sein, dass beim Hinzufügen von Zeilen (es ist eine Methode aktiviert ) zeilenweise Loadverschiedene Einschränkungen aus der Dokumentation überprüft werden müssen, DataTablewährend FillDataAdapters verwendet werden, die nur dafür entwickelt wurden - schnelle Erstellung von DataTables.

nawfal
quelle
3
Sie müssen das DataTable.Load()mit umgeben .BeginLoadData()und .EndLoadData()die gleiche Geschwindigkeit wie mit dem erreichen DataSet.
Nikola Bogdanović
1

Centerlized Model: Sie können es von jedem Ort aus verwenden!

Sie müssen nur Below Format von Ihrer Funktion zu dieser Klasse aufrufen

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

Das ist es. Es ist die perfekte Methode.

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
quelle