SQL 테이블을 C # DataTable로 읽기


답변:


159

여기, 이것을 시도하십시오 (이것은 단지 의사 코드입니다)

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의 출력 매개 변수를 갖는 것은 어떻습니까? 출력 매개 변수를 얻는 방법도? 가능할까요? 견본?
Ahmad Ebrahimi 2015

1
이 코드는 오류가 발생하기 쉬우므로 이러한 방식으로 사용 가능한 리소스를 사용하지 않는 것이 좋습니다. 깨끗한 솔루션에 대해서는 @Tim Rogers 답변을 참조하십시오.
Xan-Kun Clark-Davis

그 외에도 LINQ를 살펴보십시오 (아직하지 않은 경우). 여기에서 실제로 마법을 수행 할 수 있습니다. :-)
Xan-Kun Clark-Davis

이 코드는 작동하지만, 이것은 사용하지 않는 try/catch또는를 using()핸들 오류.
Si8

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

그런 다음 데이터 세트에서 데이터 테이블을 가져올 수 있습니다.

upvoted 답변 데이터 세트의 메모는 사용되지 않습니다. (내 답변 뒤에 나타남)

// 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을 사용하는 경우 일반적으로 ado.net 위에 위치하므로 두 기술 (EF, linq2sql, dapper, nhibernate, orm)을 모두 사용할 수 있습니다. 얻을 수있는 이점은 코드 생성을 활용하여 적절한 수준의 추상화를 제공하는 경우 스키마 변경에 따라 모델을 훨씬 쉽게 업데이트 할 수 있다는 것입니다.

ado.net 어댑터는 데이터베이스의 유형 정보를 노출하는 공급자를 사용합니다. 예를 들어 기본적으로 SQL 서버 공급자를 사용합니다. 예를 들어 devart 포스트그레스 공급자를 연결할 수도 있습니다. 그러면 유형 정보에 계속 액세스 할 수 있습니다. 위와 같이 선택한 orm을 사용할 수 있도록 허용합니다 (거의 고통없이-몇 가지 단점이 있습니다). Microsoft도 오라클 공급자를 제공한다고 생각합니다. 이것의 전적인 목적은 가능한 경우 데이터베이스 구현에서 추상화하는 것입니다.


1
형식화 된 데이터 세트에는 EF와 마찬가지로 형식 안전성과 강력한 형식의 컬렉션이 있습니다. 그러나 이는 앱이 데이터베이스에 단단히 결합 된 경우에만 해당됩니다. 다양한 데이터베이스에서 작동해야하는 도구를 작성하는 경우 형식 안전성은 절망적입니다.
Ross Presser 2014 년

1
.net에 입력 된 데이터 세트는 XML 광기와 비애의 끔찍한 생성입니다. 나는 마이크로 소프트 형식의 데이터 세트에 대한 모든 것을 유지하는 오버 헤드를 기꺼이 받아 들일 수있는 곳에서 일한 적이 없습니다. 나는 마이크로 소프트조차도 요즘 그 감각을 제안한다고 생각하지 않는다. 여러 데이터베이스의 형식 안전성에 관해서는 물론 얻을 수 있습니다. 요점은 최대한 빨리 형식화 된 컬렉션으로 변환하고이를 전달하여 형식 문제를 특정 위치로 제한한다는 것입니다. Orms는이를 지원하고 여러 데이터베이스에서 완벽하게 작동합니다. EF가 마음에 들지 않으면 더 가벼운 것을 사용하십시오.
John Nicholas

1
당신은 나를 이해하지 못했습니다. 어떤 종류의 데이터베이스에 연결할지 모르는 범용 도구를 작성하는 경우 형식 안전성은 절망적입니다.
Ross Presser 2014

1
SQL이 주어집니다. 게다가 어떤 종류의 데이터베이스를 모른다면 왜 데이터베이스 여야하나요? 그러한 일반 도구의 적용은 무엇입니까? 매우 근본적으로 다른 데이터베이스에 연결해야하는 경우 저장소 패턴 뒤에서 추상화 한 다음 그 내부에 다른 특수 데이터베이스 어댑터가 필요하며 그 시점에서 세부 사항에 대해 알 수 있습니다. 사실 소비 코드에는 유형 기대-> 어댑터의 유형 어설 션이 있습니다. 제약 조건은 데이터베이스 언어에 대해 전혀 모르기 때문에 쿼리 할 수 ​​없음을 의미합니다.
John Nicholas

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보기에는 더 좋아 보이지만 데이터 어댑터 성능이 더 좋습니다 (하나의 db가 다른 db보다 성능이 뛰어나다는 것을 혼동하지 말고 쿼리가 모두 달랐습니다). 하지만 둘의 차이는 쿼리에 따라 다릅니다. 그 이유 는 DataTables의 빠른 생성을 위해 설계된 DataAdapters에있는 동안 행을 추가 할 때 문서에서Load 행별로 다양한 제약 조건을 확인해야하기 때문일 수 있습니다 (에 메서드 ) .DataTableFill


3
당신은 서라운드 필요 DataTable.Load().BeginLoadData()하고 .EndLoadData()와 동일한 속도를 달성하기 위해 DataSet.
Nikola Bogdanović 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;
   }
  }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.