อ่านตาราง SQL ใน C # DataTable


93

ฉันได้อ่านโพสต์มากมายเกี่ยวกับการแทรก DataTable ลงในตาราง SQL แต่มีวิธีง่ายๆในการดึงตาราง SQL เข้าสู่. NET DataTable หรือไม่


8
อืม ... ใช้วิธี Fill บน DataAdapter?
John Bledsoe

คำตอบ:


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

18
datatableฟิลด์จะต้องเริ่มต้นก่อนที่จะเรียกda.Fill(dataTable)
Dabblernl

@ yonan2236 แล้วการมีพารามิเตอร์เอาต์พุตจาก t sql ข้าง datatable ล่ะ? วิธีรับพารามิเตอร์เอาต์พุตด้วย? เป็นไปได้ไหม? ตัวอย่าง?
Ahmad Ebrahimi

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?? เหมือนดูถูก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 หรือเอนทิตีเฟรมเวิร์ก) ชีวิตของคุณจะง่ายขึ้นมาก

แก้ไข: บางทีฉันอาจไม่ชัดเจน: Datatables = good, datasets = evil หากคุณใช้ ADO.Net คุณสามารถใช้ทั้งสองเทคโนโลยีเหล่านี้ (EF, linq2sql, dapper, nhibernate หรือ orm of the month) ได้ตามปกติ ข้อดีที่คุณได้รับคือคุณสามารถอัปเดตโมเดลของคุณได้ง่ายขึ้นเนื่องจากการเปลี่ยนแปลงสคีมาของคุณทำให้คุณมีระดับนามธรรมที่เหมาะสมโดยการสร้างโค้ด

อะแดปเตอร์อะแดปเตอร์อะแดปเตอร์อะแด็ปเตอร์ใช้ผู้ให้บริการที่เปิดเผยข้อมูลประเภทของฐานข้อมูลตัวอย่างเช่นโดยค่าเริ่มต้นจะใช้ผู้ให้บริการเซิร์ฟเวอร์ sql คุณยังสามารถเสียบ - เช่น - devart postgress provider และยังสามารถเข้าถึงข้อมูลประเภทซึ่งจะ อนุญาตให้คุณข้างต้นใช้ orm ที่คุณเลือก (เกือบจะไม่ลำบาก - มีนิสัยแปลก ๆ เล็กน้อย) - ฉันเชื่อว่า Microsoft มีผู้ให้บริการ oracle ด้วย จุดประสงค์ทั้งหมดของสิ่งนี้คือการแยกออกจากการใช้ฐานข้อมูลหากเป็นไปได้


1
ชุดข้อมูลที่พิมพ์มีประเภทความปลอดภัยและคอลเลกชันที่พิมพ์มากเช่นเดียวกับ EF แต่สิ่งเหล่านี้มีไว้สำหรับเมื่อแอปของคุณเชื่อมโยงกับฐานข้อมูลอย่างแน่นหนา หากคุณกำลังเขียนเครื่องมือที่ต้องทำงานกับฐานข้อมูลต่างๆประเภทความปลอดภัยเป็นความปรารถนาที่สิ้นหวัง
Ross Presser

1
ชุดข้อมูลที่พิมพ์ใน. net เป็นการสร้างความบ้าคลั่งและความฉิบหายของ xml ที่น่าสยดสยอง ฉันไม่เคยทำงานในสถานที่ที่เต็มใจยอมรับค่าใช้จ่ายในการบำรุงรักษาทั้งหมดสำหรับชุดข้อมูลที่พิมพ์โดยไมโครซอฟท์ ฉันไม่คิดว่าไมโครซอฟท์จะแนะนำว่ามันสมเหตุสมผลในทุกวันนี้ สำหรับความปลอดภัยของประเภทที่มีฐานข้อมูลหลายแห่งแน่นอนว่าคุณจะได้รับ - ประเด็นก็คือคุณแปลงเป็นคอลเลกชันที่พิมพ์โดยเร็วและส่งผ่านเพื่อให้คุณ จำกัด ปัญหาประเภทไปยังสถานที่เฉพาะ Orms จะช่วยในเรื่องนั้นและทำงานได้ดีกับฐานข้อมูลหลาย ๆ ฐานข้อมูล ถ้าคุณไม่ชอบ EF ให้ใช้อะไรที่เบากว่าเช่น dapper
John Nicholas

1
คุณไม่เข้าใจฉัน หากคุณกำลังเขียนเครื่องมือเอนกประสงค์ที่ไม่รู้ว่าจะเชื่อมต่อกับฐานข้อมูลประเภทใดความปลอดภัยก็เป็นความปรารถนาที่สิ้นหวัง
Ross Presser

1
Sql จะได้รับ นอกจากนี้หากคุณไม่รู้ว่าฐานข้อมูลประเภทใดทำไมถึงต้องเป็นฐานข้อมูลด้วย? การประยุกต์ใช้เครื่องมือทั่วไปเช่นนี้จะเป็นอย่างไร? หากคุณจำเป็นต้องเชื่อมต่อกับฐานข้อมูลที่มีความแตกต่างกันอย่างสิ้นเชิงคุณจะแยกตัวออกจากรูปแบบที่เก็บข้อมูลจากนั้นภายในนั้นคุณจะต้องใช้อะแดปเตอร์ฐานข้อมูลเฉพาะที่แตกต่างกันและ ณ จุดนั้นคุณจะรู้เกี่ยวกับข้อมูลจำเพาะ ความจริงคือการใช้รหัสมีความคาดหวังประเภท -> การยืนยันประเภทในอะแดปเตอร์ ข้อ จำกัด ของคุณหมายความว่าคุณไม่มีความคิดเกี่ยวกับภาษาของฐานข้อมูลจึงไม่สามารถสอบถามได้
John Nicholas

3
สมมติว่าคุณกำลังเขียน SSMS clone?
Ross Presser

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 ซึ่งได้รับการออกแบบมาเพื่อการนั้น - การสร้างตารางข้อมูลอย่างรวดเร็ว


3
คุณต้องล้อมรอบDataTable.Load()ด้วย.BeginLoadData()และ.EndLoadData()เพื่อให้ได้ความเร็วเช่นเดียวกับDataSet.
Nikola Bogdanović

1

Centerlized Model: คุณสามารถใช้งานได้จากทุกที่!

คุณเพียงแค่ต้องเรียกรูปแบบด้านล่างจากฟังก์ชันของคุณเป็นคลาสนี้

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;
   }
  }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.