Чтение таблицы SQL в C # DataTable

93

Я прочитал много сообщений о вставке DataTable в таблицу SQL, но есть ли простой способ вывести таблицу SQL в .NET DataTable?

Будет
источник
8
Ммм ... использовать метод Fill в DataAdapter?
Джон Бледсо

Ответы:

156

Вот, попробуйте (это всего лишь псевдокод)

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();
    }
}
йонан2236
источник
18
datatableПоле должно быть инициализирована перед вызовомda.Fill(dataTable)
Dabblernl
@ yonan2236 Как насчет наличия выходных параметров из t sql рядом с datatable? как получить выходной параметр тоже? Является ли это возможным? Образец?
Ахмад Эбрахими
1
Этот код подвержен ошибкам, поэтому использовать доступные ресурсы таким образом не рекомендуется. Пожалуйста, смотрите ответ @Tim Rogers для чистого решения.
Xan-Kun Clark-Davis
Кроме того, взгляните на LINQ (если еще не сделали этого), так как он действительно может творить чудеса :-)
Ксан-Кун Кларк-Дэвис
78
var table = new DataTable();    
using (var da = new SqlDataAdapter("SELECT * FROM mytable", "connection string"))
{      
    da.Fill(table);
}
Тим Роджерс
источник
7
@ Xan-KunClark-Davis: Код в принятом ответе приводит к утечке ресурсов при возникновении исключения. Вы могли бы не usingтак сильно презирать, если бы понимали его полный эквивалент.
Бен Фойгт
@ Xan-KunClark-Davis Почему ты презираешь Using?? Это похоже на презрение Withили Try-Catch. Я наоборот; Я разочарован, когда это не поддерживается классом.
SteveCinq
12

Много способов.

Используйте ADO.Net и заполните адаптер данных, чтобы получить 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);
}

Затем вы можете получить таблицу данных из набора данных.

Примечание в наборе данных ответов, за которые проголосовали, не используется (оно появилось после моего ответа).

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

Что предпочтительнее моего.

Я настоятельно рекомендую взглянуть на структуру сущностей ... использование таблиц и наборов данных - не лучшая идея. На них нет безопасности типов, что означает, что отладка может выполняться только во время выполнения. С строго типизированными коллекциями (которые вы можете получить с помощью LINQ2SQL или entity framework) ваша жизнь станет намного проще.

Изменить: Возможно, я не понял: Datatables = хорошо, наборы данных = зло. Если вы используете ADO.Net, вы можете использовать обе эти технологии (EF, linq2sql, dapper, nhibernate, orm of the month), поскольку они обычно находятся поверх ado.net. Преимущество, которое вы получаете, заключается в том, что вы можете намного проще обновлять свою модель по мере изменения вашей схемы, при условии, что у вас есть правильный уровень абстракции, используя генерацию кода.

Адаптер ado.net использует поставщиков, которые предоставляют информацию о типе базы данных, например, по умолчанию он использует поставщик сервера sql, вы также можете подключить - например, поставщик постгресса devart и по-прежнему получать доступ к информации о типе, которая затем будет позволяет вам, как указано выше, использовать выбранный вами orm (почти безболезненно - есть несколько причуд) - я считаю, что Microsoft также предоставляет поставщика Oracle. ВСЯ цель этого - абстрагироваться от реализации базы данных, где это возможно.

Джон Николас
источник
1
Типизированные наборы данных имеют безопасность типов и строго типизированные коллекции, как и EF. Но это только тогда, когда ваше приложение тесно связано с базой данных. Если вы пишете инструмент, который должен работать с множеством разных баз данных, безопасность типов - безнадежное желание.
Росс Прессер
1
Типизированные наборы данных в .net - это ужасное творение безумия и горя xml. Я никогда не работал в месте, которое готово принять накладные расходы на поддержание всего этого для типизированных наборов данных микрософтов. Я не думаю, что в наши дни даже Microsoft предлагает это разумно. Что касается безопасности типов с несколькими базами данных, конечно, вы можете это получить - дело в том, что вы конвертируете ее в типизированную коллекцию как можно скорее и передаете ее, чтобы ограничить проблемы типа определенным местом. Orms поможет в этом и отлично работает с несколькими базами данных. Если вам не нравится EF, используйте что-нибудь более легкое, например dapper.
Джон Николас
1
Вы меня не поняли. Если вы пишете инструмент общего назначения, который не знает, к какой базе данных он будет подключаться, то безопасность типов - безнадежное желание.
Росс Прессер
1
Sql предоставляется. Кроме того, если вы не знаете, что это за база данных, то почему она вообще должна быть базой данных? Каково было бы применение такого универсального инструмента? Если вам когда-нибудь понадобится подключиться к базам данных, которые действительно настолько радикально отличаются друг от друга, вы бы абстрагировались от него за шаблоном репозитория, а затем внутри этого вам понадобились бы другие специализированные адаптеры баз данных, и тогда вы бы узнали о специфике. Дело в том, что у потребляющего кода есть ожидания типа -> утверждения типа в адаптере. Ваше ограничение означает, что вы не имеете представления о языке базы данных и не можете делать запросы.
Джон Николас
3
Предположим, вы пишете клон SSMS?
Росс Прессер
9

Версия, не зависящая от производителя, полагается исключительно на интерфейсы ADO.NET; 2 способа:

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

Я провел некоторое тестирование производительности, и второй подход всегда превосходил первый.

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выглядит лучше на глазах, но адаптер данных работает лучше (чтобы не сбить с толку тот факт, что одна база данных превзошла другую, все запросы были разными). Однако разница между ними зависела от запроса. Причина может заключаться в том, что при добавлении строк (это метод на ) Loadтребуется проверка различных ограничений построчно из документации,DataTable а Fillна DataAdapters, которые были разработаны именно для этого - быстрое создание DataTables.

науфал
источник
3
Вы должны окружать DataTable.Load()с .BeginLoadData()и .EndLoadData()достичь той же скоростью, с DataSet.
Никола Богданович
1

Центрированная модель: вы можете использовать ее откуда угодно!

Вам просто нужно вызвать ниже формат из вашей функции в этот класс

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

Вот и все. это идеальный метод.

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;
   }
  }
Еланго Сенготтайян
источник