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();
}
}
datatablePole musi zostać zainicjowane przed wywołaniemda.Fill(dataTable)
Dabblernl
@ yonan2236 A co z parametrem wyjściowym z t sql obok datatable? jak uzyskać parametr wyjściowy też? Czy to możliwe? Próba?
Ahmad Ebrahimi
1
Ten kod jest podatny na błędy i nie zaleca się korzystania w ten sposób z dostępnych zasobów. Zobacz odpowiedź @Tim Rogers, aby uzyskać czyste rozwiązanie.
Xan-Kun Clark-Davis
Poza tym spójrz na LINQ (jeśli jeszcze tego nie zrobiłeś), ponieważ tutaj naprawdę może zdziałać magię :-)
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: Kod w zaakceptowanej odpowiedzi przecieka zasoby, jeśli zostanie zgłoszony wyjątek. Możesz nie gardzić usingtak bardzo, jeśli rozumiesz jego pełny odpowiednik.
Ben Voigt
@ Xan-KunClark-Davis Dlaczego miałbyś pogardzać Using?? To jak pogardzanie Withlub Try-Catch. Ja jestem odwrotnie; Jestem rozczarowany, gdy nie jest obsługiwany przez klasę.
SteveCinq
12
Wiele sposobów.
Użyj ADO.Net i użyj wypełnienia adaptera danych, aby uzyskać 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);
}
Następnie możesz pobrać tabelę danych ze zbioru danych.
Uwaga w zbiorze danych dotyczących odpowiedzi za pozytywnymi odpowiedziami nie jest używany (pojawiło się po mojej odpowiedzi)
// create data adapter
SqlDataAdapter da = new SqlDataAdapter(cmd);
// this will query your database and return the result to your datatable
da.Fill(dataTable);
Co jest lepsze od mojego.
Zdecydowanie zalecałbym jednak przyjrzenie się strukturze encji ... używanie danych i zestawów danych nie jest dobrym pomysłem. Nie ma na nich żadnego zabezpieczenia typów, co oznacza, że debugowanie można przeprowadzić tylko w czasie wykonywania. Dzięki kolekcjom silnie wpisanym (które można uzyskać za pomocą LINQ2SQL lub frameworku jednostek) Twoje życie będzie o wiele łatwiejsze.
Edycja: Być może nie było jasne: dane = dobre, zbiory danych = zło. Jeśli używasz ADO.Net, możesz użyć obu tych technologii (EF, linq2sql, dapper, nhibernate, orm of the month), ponieważ zazwyczaj znajdują się one na szczycie ado.net. Zaletą jest to, że możesz znacznie łatwiej zaktualizować model, gdy zmieni się schemat, pod warunkiem, że masz odpowiedni poziom abstrakcji, wykorzystując generowanie kodu.
Adapter ado.net korzysta z dostawców, którzy ujawniają informacje o typie bazy danych, na przykład domyślnie korzysta z dostawcy serwera sql, możesz również podłączyć - na przykład - dostawcę postgress devart i nadal uzyskać dostęp do informacji o typie, które następnie pozwalają ci jak wyżej korzystać z twojego wyboru (prawie bezboleśnie - jest kilka dziwactw) - uważam, że Microsoft również zapewnia dostawcę Oracle. CAŁKOWITYM celem tego jest oderwanie się od implementacji bazy danych tam, gdzie to możliwe.
Typowane zestawy danych mają bezpieczeństwo typów i kolekcje silnie wpisane, podobnie jak EF. Ale to tylko wtedy, gdy Twoja aplikacja jest ściśle powiązana z bazą danych. Jeśli piszesz narzędzie, które ma współpracować z wieloma różnymi bazami danych, bezpieczeństwo typów jest beznadziejnym życzeniem.
Ross Presser
1
Wpisane zbiory danych w .net są okropnym dziełem szaleństwa i niedoli XML. Nigdy nie pracowałem w miejscu, które jest skłonne zaakceptować narzut związany z utrzymaniem tego wszystkiego dla zestawów danych wpisanych w mikrosoftach. Nie sądzę, żeby nawet Microsoft sugerował, że jest to rozsądne w dzisiejszych czasach. Jeśli chodzi o bezpieczeństwo typów z wieloma bazami danych, oczywiście możesz to uzyskać - chodzi o to, że konwertujesz je na kolekcję wpisaną jak najszybciej i przekazujesz to, aby ograniczyć problemy z typami do określonego miejsca. Orms pomoże w tym i doskonale współpracuje z wieloma bazami danych. Jeśli nie lubisz EF, użyj czegoś lżejszego, na przykład eleganckiego.
John Nicholas
1
Nie zrozumiałeś mnie. Jeśli piszesz narzędzie ogólnego przeznaczenia, które nie ma pojęcia, z jaką bazą danych będzie się łączyć, bezpieczeństwo typów jest beznadziejnym życzeniem.
Ross Presser,
1
Sql jest podane. Poza tym, jeśli nie wiesz, jaki rodzaj bazy danych, dlaczego w ogóle musi to być baza danych? Jakie byłoby zastosowanie takiego ogólnego narzędzia? Jeśli kiedykolwiek będziesz musiał połączyć się z bazami danych, które są naprawdę tak radykalnie różne, odejdziesz od nich za wzorcem repozytorium, a następnie będziesz potrzebować różnych wyspecjalizowanych adapterów bazy danych i wtedy będziesz wiedział o szczegółach. Faktem jest, że kod konsumujący ma oczekiwania typu -> potwierdzenia typu w adapterze. Twoje ograniczenie oznacza, że nie masz pojęcia o języku bazy danych i nie możesz wykonywać zapytań.
John Nicholas
3
Załóżmy, że piszesz klon SSMS?
Ross Presser
9
Wersja niezależna od dostawcy, oparta wyłącznie na interfejsach ADO.NET; 2 drogi:
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];
}
}
}
}
Zrobiłem kilka testów wydajności i drugie podejście zawsze było lepsze od pierwszego.
Read1wygląda lepiej na oczach, ale adapter danych działa lepiej (aby nie mylić, że jedna baza danych przewyższa drugą, zapytania były różne). Różnica między nimi zależała jednak od zapytania. Powodem może być to, że podczas dodawania wierszy Loadwymagane jest sprawdzanie różnych ograniczeń wiersz po wierszu z dokumentacji podczas dodawania wierszy (jest to metoda włączona DataTable), podczas gdy Filljest to na adapterach DataAdapters, które zostały zaprojektowane specjalnie do tego celu - szybkie tworzenie DataTables.
Musisz otoczyć DataTable.Load()z .BeginLoadData()i .EndLoadData()osiągnąć taką samą prędkość jak w przypadku DataSet.
Nikola Bogdanović
1
Model centralny: możesz go używać z dowolnego miejsca!
Wystarczy wywołać funkcję Below Format From do tej klasy
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);
Otóż to. to doskonała metoda.
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;
}
}
Odpowiedzi:
Tutaj, daj temu szansę (to tylko pseudokod)
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(); } }
źródło
datatable
Pole musi zostać zainicjowane przed wywołaniemda.Fill(dataTable)
var table = new DataTable(); using (var da = new SqlDataAdapter("SELECT * FROM mytable", "connection string")) { da.Fill(table); }
źródło
using
tak bardzo, jeśli rozumiesz jego pełny odpowiednik.Using
?? To jak pogardzanieWith
lubTry-Catch
. Ja jestem odwrotnie; Jestem rozczarowany, gdy nie jest obsługiwany przez klasę.Wiele sposobów.
Użyj ADO.Net i użyj wypełnienia adaptera danych, aby uzyskać 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); }
Następnie możesz pobrać tabelę danych ze zbioru danych.
Uwaga w zbiorze danych dotyczących odpowiedzi za pozytywnymi odpowiedziami nie jest używany (pojawiło się po mojej odpowiedzi)
// create data adapter SqlDataAdapter da = new SqlDataAdapter(cmd); // this will query your database and return the result to your datatable da.Fill(dataTable);
Co jest lepsze od mojego.
Zdecydowanie zalecałbym jednak przyjrzenie się strukturze encji ... używanie danych i zestawów danych nie jest dobrym pomysłem. Nie ma na nich żadnego zabezpieczenia typów, co oznacza, że debugowanie można przeprowadzić tylko w czasie wykonywania. Dzięki kolekcjom silnie wpisanym (które można uzyskać za pomocą LINQ2SQL lub frameworku jednostek) Twoje życie będzie o wiele łatwiejsze.
Edycja: Być może nie było jasne: dane = dobre, zbiory danych = zło. Jeśli używasz ADO.Net, możesz użyć obu tych technologii (EF, linq2sql, dapper, nhibernate, orm of the month), ponieważ zazwyczaj znajdują się one na szczycie ado.net. Zaletą jest to, że możesz znacznie łatwiej zaktualizować model, gdy zmieni się schemat, pod warunkiem, że masz odpowiedni poziom abstrakcji, wykorzystując generowanie kodu.
Adapter ado.net korzysta z dostawców, którzy ujawniają informacje o typie bazy danych, na przykład domyślnie korzysta z dostawcy serwera sql, możesz również podłączyć - na przykład - dostawcę postgress devart i nadal uzyskać dostęp do informacji o typie, które następnie pozwalają ci jak wyżej korzystać z twojego wyboru (prawie bezboleśnie - jest kilka dziwactw) - uważam, że Microsoft również zapewnia dostawcę Oracle. CAŁKOWITYM celem tego jest oderwanie się od implementacji bazy danych tam, gdzie to możliwe.
źródło
Wersja niezależna od dostawcy, oparta wyłącznie na interfejsach ADO.NET; 2 drogi:
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]; } } } }
Zrobiłem kilka testów wydajności i drugie podejście zawsze było lepsze od pierwszego.
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
wygląda lepiej na oczach, ale adapter danych działa lepiej (aby nie mylić, że jedna baza danych przewyższa drugą, zapytania były różne). Różnica między nimi zależała jednak od zapytania. Powodem może być to, że podczas dodawania wierszyLoad
wymagane jest sprawdzanie różnych ograniczeń wiersz po wierszu z dokumentacji podczas dodawania wierszy (jest to metoda włączonaDataTable
), podczas gdyFill
jest to na adapterach DataAdapters, które zostały zaprojektowane specjalnie do tego celu - szybkie tworzenie DataTables.źródło
DataTable.Load()
z.BeginLoadData()
i.EndLoadData()
osiągnąć taką samą prędkość jak w przypadkuDataSet
.Model centralny: możesz go używać z dowolnego miejsca!
Wystarczy wywołać funkcję Below Format From do tej klasy
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);
Otóż to. to doskonała metoda.
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; } }
źródło