将SQL表读入C#DataTable


Answers:


155

在这里,给它一个镜头(这只是一个伪代码)

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
datatable在致电之前必须初始化该字段da.Fill(dataTable)
Dabblernl 2014年

@ yonan2236从t sql在数据表旁边获取输出参数怎么样?如何获得输出参数呢?可能吗?样品?
艾哈迈德·埃布拉希米

1
该代码容易出错,不建议以这种方式使用可用资源。请参阅@Tim Rogers答案以获得干净的解决方案。
Xan-Kun Clark-Davis

除此之外,看看LINQ(如果还没有的话),因为它确实可以在这里起到一些神奇作用:-)
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:如果引发异常,则接受的答案中的代码会泄漏资源。using如果您了解其完全等同的功能,则可能不会轻视它。
Ben Voigt

@ Xan-KunClark-Davis为什么会鄙视Using?就像鄙视WithTry-Catch。我是相反的;当一个类不支持它时,我很失望。
SteveCinq '18

12

有很多方法。

使用ADO.Net并在数据适配器上使用fill来获取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或实体框架中获得),您的生活会容易得多。

编辑:也许我不清楚:数据表=好,数据集=邪恶。如果您使用的是ADO.Net,则可以同时使用这两种技术(EF,linq2sql,dapper,nhibernate和本月的orm),因为它们通常位于ado.net之上。您获得的好处是,通过利用代码生成,只要您具有正确的抽象级别,就可以随着模式更改轻松地更新模型。

ado.net适配器使用提供程序来公开数据库的类型信息,例如默认情况下它使用sql服务器提供程序,您也可以插入-例如-devart postgress提供程序,并且仍然可以访问类型信息允许您像上面那样使用您选择的格式(几乎不费力-有一些怪癖)-我相信Microsoft还提供了Oracle提供程序。整个目的是在可能的情况下从数据库实现中抽象出来。


1
就像EF一样,类型化数据集具有类型安全性和强类型化集合。但是,这些仅适用于您的应用程序与数据库紧密耦合的情况。如果您正在编写必须与许多不同的数据库一起使用的工具,则类型安全性是绝望的希望。
Ross Presser 2014年

1
.net中的类型化数据集是xml疯狂和灾难的可怕创造。我从来没有在一个愿意接受为Microsoft类型数据集维护所有这些开销的地方工作过。我认为,即使是微软,这些天也没有提出明智的建议。至于具有多个数据库的类型安全性,您当然可以得到-关键是将其尽快转换为类型化集合并将其传递给您,以便将类型问题限制在特定位置。Orms可以帮助您解决此问题,并且可以与多个数据库完美配合。如果您不喜欢EF,请使用较轻巧的东西。
约翰·尼古拉斯

1
你不懂我 如果您编写的通用工具不知道它将连接到哪种数据库,则类型安全性是绝望的希望。
Ross Presser 2014年

1
给出了sql。此外,如果您不知道哪种数据库,那为什么还必须是数据库呢?这种通用工具的用途是什么?如果您需要连接到真正有很大不同的数据库,则可以从存储库模式中抽象出来,然后在其中进行抽象,然后需要使用不同的专用数据库适配器,届时您将了解具体细节。事实是,消耗代码的代码具有类型期望->适配器中的类型断言。您的约束意味着您不了解数据库语言,因此无法查询。
约翰·尼古拉斯

3
假设您正在编写SSMS克隆?
Ross Presser 2014年

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看起来更好,但是数据适配器的性能更好(不要混淆一个数据库优于另一个数据库,查询是完全不同的)。两者之间的差异取决于查询。原因可能是,当在仅用于此目的的DataAdapters上添加行时(在上的方法),Load需要从文档中逐行检查各种约束-快速创建DataTables。DataTableFill


3
您需要将和包围DataTable.Load()起来.BeginLoadData().EndLoadData()以达到与相同的速度DataSet
NikolaBogdanović2014年

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;
   }
  }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.