'dataset'에 해당되는 글 2건

Programming/.NET

 1. DataSet 과 XML

 

기본적으로 DataSet의 데이터를 XML로 표시하는건 간단합니다.

 

using (SqlConnection conn = new SqlConnection(con)) {
    SqlCommand cmd = new SqlCommand("Select * From BOOK;", conn);
    conn.Open();

    DataSet ds = new DataSet();
    ds.DataSetName = "books";
    ds.Load(cmd.ExecuteReader(), LoadOption.OverwriteChanges, "book");

    Response.ContentType = "text/xml";
    ds.WriteXml(Response.OutputStream);
}

 

DataSetName은 XML에 대응해 최상위노드에 해당합니다. 그리고 Load메소드의 마지막 인자로 전달한 book은 TableName을 지정하는 것인데 XML에서는 최상위노드 하위의 개별요소로 작용합니다. 그 다음 마지막에 WriteXml 메소드를 호출하여 DB로부터 읽어들인 Table개체를 XML로 표시하도록 하였습니다.

 

 2. XmlDataDocument

 

XmlDataDocument클래스는 DataSet클래스에서 작성된 XML에 대해 좀더 구체적이고 유연한 컨트롤방법을 제공하는 클래스입니다.

 

using (SqlConnection conn = new SqlConnection(con)) {
    SqlCommand cmd = new SqlCommand("Select * From BOOK;", conn);
    conn.Open();

    DataSet ds = new DataSet();
    ds.DataSetName = "books";
    ds.Load(cmd.ExecuteReader(), LoadOption.OverwriteChanges, "book");

    XmlDataDocument xdd = new XmlDataDocument(ds);
    XmlNodeList xnl = xdd.SelectNodes("//books/book/title");

    foreach (XmlNode xn in xnl)
        Response.Write(xn.InnerText + "<br />");
}

 

XmlDataDocument 클래스의 생성자로 DataSet을 넘겨주면 XmlDocument API로 DataSet의 XML접근을 가능하게 하며 인자로 넘겨준 DataSet을 기반으로한 XmlDataDocument의 DataSet을 제공하기도 합니다.

 

XmlDataDocument xdd = new XmlDataDocument(ds);
XmlNodeList xnl = xdd.SelectNodes("//books/book/title");

xdd.DataSet.EnforceConstraints = false;
foreach (XmlNode xn in xnl)
    xn.InnerText = "이건 제목";

foreach (DataRow dr in ds.Tables[0].Rows)
    Response.Write(dr[2].ToString() + "<br />");

 

이전 예제는 단순히 XML로 데이터를 불러와 보여주는데 그쳤지만 위 예제는 직접 XML의 데이터를 바꾸는 동작을 수행합니다. 이게 재미있는게 일단 DataSet을 통해 XmlDataDocument객체를 생성하면 해당 객체와 인자로 넘겨준 DataSet이 연결된다는 것입니다. 그래서 XML데이터를 바꾸면 그 값이 DataSet에도 그대로 반영됩니다. 다만 실제 데이터를 바꾸려면 XmlDataDocument클래스의 EnforceConstraints를 true로 설정해야 합니다.

 

xdd.DataSet.EnforceConstraints = false;
foreach (XmlNode xn in xnl) {
    xn.InnerText = "이건 제목";

    DataRow dr = xdd.GetRowFromElement((XmlElement)xn.ParentNode);
    Response.Write(dr[2].ToString() + "<br />");
}

 

변경된 데이터는 직접 DataSet 데이터를 순회하여 확인할 수 있고 아니면 XML노드를 다시 DataSet의 Row객체로 변환해 바로 보는것도 가능합니다.

'Programming > .NET' 카테고리의 다른 글

[ASP.NET] Calender  (0) 2016.03.07
[ASP.NET] DataList  (0) 2016.03.03
[ASP.NET] XML - 6  (0) 2016.02.23
[ASP.NET] XML - 5  (0) 2016.02.18
[ASP.NET] XML - 4  (0) 2016.02.11
[ASP.NET] XML - 3  (0) 2016.02.01
0 0
Programming/.NET
DataSet 클래스는 ADO.NET 에서 가장 핵심 클래스중 하나로서 데이터 소스와의 비연결 상태에서도 데이터를 다룰 수 있게 하는 방안을 제공하고 있습니다. 이는 ADO.NET 1.0 이 처음발표 될때부터 소개된 것으로 지금까지도 계속 발전해 나가고 있습니다.

DataSet 클래스로 부터 생성된 객체는 DataTable 클래스 객체의 컨테이너로서 동작합니다. 여기서 DataTable 객체는 메모리상의 논리적인 테이블을 의미하는 것으로 행, 열은 물론 키, 제약조건이나 다른 DataTable 과의 관계구조까지도 포함됩니다. 데이터 소스의 Table 구조를 그대로 복사해 오는 것과 같은데 심지어 DataSet 은 DataTable 객체의 컨테이너에 해당되므로 두개이상의 DataTable 과의 관계로 구성된 객체를 그대로 포함할 수 있습니다.

이전의 ADO.NET 에서는 DataTable 에 바로 접근하는 방법을 허용하지 않았으며 DataSet 을 통해서만 DataTable 에 접근할 수 있었습니다. 현재는 이 제한이 사라졌으며 다중 DataTable 객체에 대한 관리나 작업이 필요하지 않다면 굳이 성능상 DataSet 사용을 권장하지는 않습니다.

현재 ADO.NET은 DataReader 를 개체로 사용하여 메모리에 DataTable을 로드하는 기능을 제공하며 한번 작성된 데이터 접근 코드를 이용해 DataReader 를 재사용 할 수 있는 유연성을 가지고 있습니다.
SqlConnection MyConnection = new SqlConnection();
 
MyConnection.ConnectionString = ConfigurationManager.ConnectionStrings["new_connection"].ConnectionString;
            
SqlCommand MyCommand = new SqlCommand();
MyCommand.CommandText = "Select Top 100 * From [Person].[PersonPhone]";
MyCommand.CommandType = CommandType.Text;
MyCommand.Connection = MyConnection;
 
MyCommand.Connection.Open();
 
SqlDataReader MyReader = MyCommand.ExecuteReader(CommandBehavior.CloseConnection);
DataTable MyDataTable = new DataTable();
MyDataTable.Load(MyReader);
 
GridView.DataSource = MyDataTable;
GridView.DataBind();
            
MyCommand.Dispose();
MyConnection.Dispose();
▶ 예제 1-1

위 코드에서 DataTable 은 DataReader 를 개체로 하여 데이터를 로드하는 예제를 보여주고 있습니다. 이처럼 DataReader 객체로 부터 DataTable 객체 데이터를 로드할 수 있을 뿐만 아니라 이미 존재하는 DataTable 객체에서 DataTableReader 를 끄집에 내는것도 가능합니다. 단지 DataTable 객체에서 DataTableReader 객체의 인스턴스를 반환하는 DataReader 생성 메소드를 호출하기만 하면 되는것입니다.

ADO 2.6 에서는 대용량 데이터에 명령을 수행하면 여러 행으로 구성된 단일 데이터 집합을 얻을 수 있었으나 현재의 ADO.NET 은 실제 구조를 유지하는 데이터 집합을 반환하기 위해 DataSet 을 사용하기도 합니다. 어떤 경우는 DataSet을 통해 본래 데이터 구조에 대한 복사본을 유지하는 것이 성능상 이점을 제공해 줄 수 있기 때문입니다. 비연결 데이터를 메모리상에 유지하며 특정 Table을 대상으로 작업하거나 Table 간의 관계를 적용시킬 수 있습니다. Table 간의 관계가 명확하게 드러난 채로 작업이 되어야 하는 경우라면 당연히 DataSet을 사용하는 편이 나을 것입니다.

DataSet 은 원본데이터를 비연결상태에서 다루기 위한 복사본이므로 원본하고는 무관하게 원본과 같은 데이터를 다룰 수 있는 이점을 제공하기도 합니다. 이것은 성능상이나 혹은 서버의 부하를 줄일 수 있는 방법이 될 수 있는데 다만 말 그대로 복사본이므로 DataSet 에 데이터의 변경, 삭제, 추가등의 작업을 하여도 개발자 임의로 적용을 시도하지 않는 한 데이터 소스원본에는 영향을 주지 않습니다.

DataSet 을 사용함으로서 얻을 수 있는 또다른 이점은 별도의 데이터 소스에 있는 데이터를 지역적으로 통합하여 다룰 수 있다는 것입니다. 예를 들어서 A 사의 고객정보는 SQL 서버 테이블에 있고 B 사의 고객정보는 Oracle 서버 테이블이 있다고 한다면 이 두 테이블 데이터를 하나의 DataSet 에 담아두고 다루는것도 가능합니다. 게다가 내부 데이터에 대한 대량의 XML 로의 전환이 가능하므로 DataSet 자체를 이해할 수 없는 이기종간의 시스템이나 애플리케이션 사이를 XML을 통하여 쉽게 전송하고 데이터를 통합할 수 있습니다.

아래는 예제 1-1 코드에서 DataSet 을 사용하도록 수정한 예제입니다.
SqlConnection MyConnection = new SqlConnection();
 
MyConnection.ConnectionString = ConfigurationManager.ConnectionStrings["new_connection"].ConnectionString;
            
SqlCommand MyCommand = new SqlCommand();
MyCommand.CommandText = "Select Top 100 * From [Person].[PersonPhone]";
MyCommand.CommandType = CommandType.Text;
MyCommand.Connection = MyConnection;
 
MyCommand.Connection.Open();
 
SqlDataAdapter sda = new SqlDataAdapter(MyCommand);
DataSet ds = new DataSet();
sda.Fill(ds, "phoneTable");
 
GridView.DataSource = ds;
GridView.DataBind();
            
MyCommand.Dispose();
MyConnection.Dispose();
여러 이점이 있기는 하지만 DataSet은 어느상황에서나 최적의 방안을 제공해 주지는 않습니다. 가장 큰 예로 꽤 큰 덩치를 들 수 있는데 이는 앞서 말씀드린 것처럼 단순한 데이터를 벗어나 테이블간의 관계등 원본과 같은 몇몇가지 속성을 DataSet 이 모두 가지고 있기 때문입니다. 이렇게 무거운 DataSet 은 방문자가 ASP.NET Web Form 페이지를 요구할때 마다 데이터 소스의 호출로 인해 페이지가 다시 재생성되는 동작이 반복되며 DataSet 또한 별도로 캐싱처리하지 않는 한 페이지와 마찬가지로 재생성 동작을 거치게 됩니다. 테이블에 관한 여러 정보대신 약간의 데이터만을 다루면 되는 상황이라면 DataSet 보다는 DataReader 클래스를 사용하여 데이터소스의 직접적인 접근을 시도하는 것이 편이 훨씬 나을지도 모릅니다.

DataSet 을 사용함에 있어 오류를 줄이고 좀더 간단한 형태의 접근이 필요하다면 Typed DataSet 을 사용할 수 있습니다. 예를 들어 Typed DataSet 이전에 코드는 아래와 같았습니다.
ds.Tables["phoneTable"].Rows[0]["PhoneNumber"] = "000-000-0000";
다소 극단적이긴 하지만 위 코드는 phoneTable 이라는 이름의 테이블에 첫번째 Row 에서 PhoneNumber 열값을 바꾸는 동작을 수행합니다. 하지만 위 코드가 정확히 수행되려면 반드시 phoneTable 이라는 테이블이 있어야 하며 PhoneNumber 라는 열값이 존재한다는게 보장되어야 합니다. 이름을 지정할때 실수로 한글자라도 틀리게 되면 Application 은 아마 오류를 내뱉을 것입니다.

이런 피곤한 방식을 탈피하기 위해 Typed DataSet 을 사용하려면 우선 프로젝트에 DataSet 을 다음과 같이 추가합니다.


Server Explorer 에서 DataSet 대상이될 위에서 생성한 xsd 위에 끌어다 놓습니다.


예제 1-1 에서 사용한 DataSet 대신 방금 생성한 DataSet 을 객체화 하여 사용합니다.
SqlConnection MyConnection = new SqlConnection();
 
MyConnection.ConnectionString = ConfigurationManager.ConnectionStrings["new_connection"].ConnectionString;
            
SqlCommand MyCommand = new SqlCommand();
MyCommand.CommandText = "Select Top 100 * From [Person].[PersonPhone];";
MyCommand.CommandType = CommandType.Text;
MyCommand.Connection = MyConnection;
 
MyCommand.Connection.Open();
 
SqlDataAdapter sda = new SqlDataAdapter(MyCommand);
myData md = new myData();
sda.Fill(md, "PersonPhone");
 
md.PersonPhone[0].PhoneNumber = "000-000-0000";
 
GridView.DataSource = md;
GridView.DataBind();
            
MyCommand.Dispose();
MyConnection.Dispose();
Typed DataSet 을 사용하면 위 예제처럼 md.PersonPhone[0].PhoneNumber 과 같이 Table 명명을 구체화 할 수 있게 됩니다.

'Programming > .NET' 카테고리의 다른 글

[ASP.NET] IAsyncResult 인터페이스  (0) 2015.04.20
[ASP.NET] LINQ 활용  (0) 2014.10.07
[ASP.NET] DataSet  (0) 2014.10.06
[ASP.NET] WaitHandle  (0) 2014.10.02
[ASP.NET] SqlCommand  (0) 2014.09.20
[ASP.NET] SqlParameter  (0) 2014.09.05
0 0
1
블로그 이미지

클리엘