'ado.net'에 해당되는 글 5건

Programming/.NET
ADO.NET 의 비동기 처리 방법에는 대략적으로 아래와 같은 방법이 존재합니다.

 IAsyncResult 폴딩

이 방법은 비동기 처리를 시작한 이후 처리완료를 전달받기 위해 IAsyncResult 객체를 통해 폴링을 시도하는 방법입니다. 아래 코드를 참고해 주세요.
SqlConnection DBCon = new SqlConnection();
DBCon.ConnectionString = ConfigurationManager.ConnectionStrings["new_connection"].ConnectionString;
            
SqlCommand Command = new SqlCommand();
Command.CommandText = "Select Top 100 * From [Person].[PersonPhone];";
Command.CommandType = CommandType.Text;
Command.Connection = DBCon;
 
DBCon.Open();
 
IAsyncResult ASyncResult = Command.BeginExecuteReader();                
            
while (!ASyncResult.IsCompleted) {
    System.Threading.Thread.Sleep(10000);
}
 
SqlDataReader PhoneReader = Command.EndExecuteReader(ASyncResult);
 
GridView1.DataSource = PhoneReader;
GridView1.DataBind();                
            
DBCon.Close();
위 코드는 PersonPhone 테이블로 부터 상위 100개의 데이터를 가져오는 기능을 수행하는데 SqlCommand 의 객체인 Command 의 BeginExcuteReader() 메소드가 수행되면 프로그램에서 비동기 처리가 시작됩니다. 이 후 처리가 완료될때가지 While 문을 통해 대기하게 되는데 이때 사용된 IAsyncResult 객체의 IsCompleted 속성으로 완료여부를 확인하게 됩니다.
(참고 : 비동기 동작이 제대로 확인되지 않으면 연결문자열에서 Asynchronous Processing=True 구문이 추가되어 있는지 확인해야 합니다.)

참고로 SqlConnection 클래스에는 State 속성을 제공하고 있는데 이 값에 따라 현재 데이터 DB 와의 연결상태를 파악할 수 있습니다.
 
 대기핸들과의 연동

비동기 처리가 시작되고 전체 혹은 일부의 처리가 완료될때 까지 대기하는 대기핸들과의 연동을 시도하는 방법으로서 비동기 처리 방법중 가장 권장되고 있는 방법이기도 합니다. 또한 이 방법은 다중 비동기 처리와 함께 전체 혹은 일부 처리가 동작을 끝낼때 까지 대기할 수 있도록 프로그램을 작성할 수 있을 뿐만 아니라 더 나아가 서로 의존하는 프로세스들을 대기시키고 그외 다른 프로세스는 별도로 처리하는 구현도 가능하게 합니다.

아래 코드는 WaitHandle 클래스의 WaitOne 메소드가 사용된 예제입니다. 이 메소드가 호출되면 비동기 프로세스가 동작을 끝낼때 까지 대기하게 되고 동작을 완료하면(true) 원하는 처리를 수행할 수 있도록 코드를 작성할 수 있습니다..
SqlConnection DBCon = new SqlConnection();
DBCon.ConnectionString = ConfigurationManager.ConnectionStrings["new_connection"].ConnectionString;
            
SqlCommand Command = new SqlCommand();
Command.CommandText = "Select Top 100 * From [Person].[PersonPhone];";
Command.CommandType = CommandType.Text;
Command.Connection = DBCon;
 
DBCon.Open();
 
IAsyncResult ASyncResult = Command.BeginExecuteReader();
System.Threading.WaitHandle WHandle = ASyncResult.AsyncWaitHandle;
 
if (WHandle.WaitOne() == true) {
    SqlDataReader PhoneReader = Command.EndExecuteReader(ASyncResult);
    GridView1.DataSource = PhoneReader;
    GridView1.DataBind();
    DBCon.Close();
}
else {
    
}
else 이하 부분은 비동기 프로세스에 대해 타임아웃등의 문제로 인하여 동작을 제대로 수행하지 못한 경우로서 예외사항을 따로 작성해 두면 됩니다.

단일이 아닌 다중 대기핸들을 사용하는 경우도 크게 다르지 않습니다. 다중 핸들에서 적용할 Command, DataReader 등 쿼리 수행에 필요한 객체등을 각각따로 생성하고 그 만큼 이들 객체에 적용할 대기핸들을 생성해 사용하면 됩니다.
SqlConnection DBCon = new SqlConnection();
DBCon.ConnectionString = ConfigurationManager.ConnectionStrings["new_connection"].ConnectionString;
 
SqlCommand Command1 = new SqlCommand();
Command1.CommandText = "Select Top 100 * From [Person].[PersonPhone];";
Command1.CommandType = CommandType.Text;
Command1.Connection = DBCon;
 
SqlCommand Command2 = new SqlCommand();
Command2.CommandText = "Select Top 10 * From [Person].[PersonPhone];";
Command2.CommandType = CommandType.Text;
Command2.Connection = DBCon;
 
DBCon.Open();
 
IAsyncResult ASyncResult1 = Command1.BeginExecuteReader();
IAsyncResult ASyncResult2 = Command2.BeginExecuteReader();
 
System.Threading.WaitHandle[] WHandles = new System.Threading.WaitHandle[2];
 
System.Threading.WaitHandle top100WHandle = ASyncResult1.AsyncWaitHandle;
System.Threading.WaitHandle top10WHandle = ASyncResult2.AsyncWaitHandle;
 
WHandles[0] = top100WHandle;
WHandles[1] = top10WHandle;
 
System.Threading.WaitHandle.WaitAll(WHandles);
 
SqlDataReader phoneReader1 = Command1.EndExecuteReader(ASyncResult1);
SqlDataReader phoneReader2 = Command2.EndExecuteReader(ASyncResult2);
 
//회수된 데이터의 처리코드
 
DBCon.Close();
다만 데이터베이스에 연결하는 객체는 하나를 사용하는데 이럴 경우 연결문자열에 Multiple Active Result Set (MARS) 을 지원할 수 있도록 MultipleActiveResultSets=True 구문을 추가해야 합니다.

다중 대기핸들을 사용하는 경우 위에서 쓰인 WaitAll 메소드 보다는 WaitAny 메소드를 사용하는 경우가 많은데 WaitAny 메소드는 각각의 비동기 처리가 끝나면 다른 프로세스가 끝날때 까지 대기하는것 없이 바로 해당 프로세스의 처리 결과를 다룰 수 있도록 합니다. 반면 WaitAll 메소드는 배열에 있는 모든 프로세스가 완료되어야 결과를 반환하는 형태의 동작을 수행합니다.
SqlConnection DBCon1 = new SqlConnection();
DBCon1.ConnectionString = ConfigurationManager.ConnectionStrings["new_connection"].ConnectionString;
 
SqlConnection DBCon2 = new SqlConnection();
DBCon2.ConnectionString = ConfigurationManager.ConnectionStrings["new_connection"].ConnectionString;
 
SqlCommand Command1 = new SqlCommand();
Command1.CommandText = "Select Top 100 * From [Person].[PersonPhone];";
Command1.CommandType = CommandType.Text;
Command1.Connection = DBCon1;
 
SqlCommand Command2 = new SqlCommand();
Command2.CommandText = "Select Top 10 * From [Person].[PersonPhone];";
Command2.CommandType = CommandType.Text;
Command2.Connection = DBCon2;
 
DBCon1.Open();
DBCon2.Open();
 
IAsyncResult ASyncResult1 = Command1.BeginExecuteReader();
IAsyncResult ASyncResult2 = Command2.BeginExecuteReader();
 
System.Threading.WaitHandle top100WHandle = ASyncResult1.AsyncWaitHandle;
System.Threading.WaitHandle top10WHandle = ASyncResult2.AsyncWaitHandle;
 
System.Threading.WaitHandle[] Handles = new System.Threading.WaitHandle[] { top100WHandle, top10WHandle };
 
for (int index = 0; index < 2; index++) {
    switch (System.Threading.WaitHandle.WaitAny(Handles)) {
        case 0:
            SqlDataReader phoneReader1 = Command1.EndExecuteReader(ASyncResult1);
            GridView1.DataSource = phoneReader1;
            GridView1.DataBind();
            DBCon1.Close();
            break;
        case 1:
            SqlDataReader phoneReader2 = Command2.EndExecuteReader(ASyncResult2);
            GridView2.DataSource = phoneReader2;
            GridView2.DataBind();
            DBCon2.Close();
            break;
    }
}
위 코드는 WaitAll 대신 WaitAny 메소드를 사용하도록 수정된 예제입니다. WaitAny 메소드는 결과로 정수형의 값을 반환하는데 이 값은 위에서 지정한 대기핸들에 대한 배열의 Index 번호에 해당합니다. 즉, WaitAny는 특정 프로세스가 처리를 완료하면 해당 프로세스에 대한 배열의 Index 값을 반환하고 곧 이 값을 확인하면 현재 완료된 프로세스를 알 수 있게 되는 것입니다.

 CallBack 사용

비동기 프로세스를 시작하는 동안 콜백(callback) 메소드를 사용하는 방법으로서 다른 작업을 병렬적으로 수행할 수 있도록 하며 비동기 프로세스가 종료될때 프로세스를 정리하고 비동기 처리가 종료되면 특정 메소드를 불러 들일 수 있도록 callback 메소드를 호출합니다. 아래 코드를 참고해 주세요.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Webtest.Default" Async="true" %>
우선 위와 같이 페이지에 Async="true" 항목을 추가설정합니다.
BeginEventHandler _begin = new BeginEventHandler(this._Begin);
EndEventHandler _end = new EndEventHandler(this._End);
AddOnPreRenderCompleteAsync(_begin, _end);
그런다음 비동기 프로세스를 시작하는 메소드(_Begin)와 끝난뒤 호출될 CallBack 메소드(_End)에 대한 이벤트 핸들러를 등록하고 AddOnPreRenderCompleteAsync 메소드를 사용해 Page 의 PreRender 이벤트 단계에서 메소드가 모두 처리될 수 있도록 동기화합니다. 이러한 작업이 필요한 이유는 비동기 특성상 Page Load 가 모두 이루어지고 난 이후에 실제 처리가 완료될 수 있는데 Page 자체에 결과에 대한 표시를 하려는 경우 제대로된 결과를 볼 수 없기 때문입니다.
IAsyncResult _Begin(object sender, EventArgs e, AsyncCallback callback, object state)
{
    SqlConnection DBCon = new SqlConnection();
    DBCon.ConnectionString = ConfigurationManager.ConnectionStrings["new_connection"].ConnectionString;
 
    Command = new SqlCommand();
    Command.CommandText = "Select Top 10 * From [Person].[PersonPhone];";
    Command.CommandType = CommandType.Text;
    Command.Connection = DBCon;
 
    DBCon.Open();
 
    AsyncCallback AsyncResult = new AsyncCallback(_End);
 
    return Command.BeginExecuteReader(callback, state, CommandBehavior.CloseConnection);
}
이제 비동기 처리가 시작될 _Begin 메소드를 위와 같이 작성합니다. 비동기 처리는 BeginExecuteReader 메소드를 호출하면서 시작되며 메소드의 동작이 완료되면 콜백으로 처리가 넘어가게 됩니다.
public void _End(IAsyncResult ar)
{
    SqlDataReader PhoneReader = Command.EndExecuteReader(ar);
 
    GridView1.DataSource = PhoneReader;
    GridView1.DataBind();
}
CallBack 메소드입니다. 메소드에 보이는 Command 객체는 _Begin 메소드에서 사용된 것과 일치하므로 Command 객체는 전역변수로서 선언하도록 합니다.

SqlCommand Command;
 비동기화 처리 취소

비동기처리는 프로그램의 실행흐름과 데이터처리 사이에 동기화를 하지 않고 프로그램실행을 계속 진행해 나갈 수 있다는 장점이 있지만 비동기처리가 예상외로 오래 걸리는 경우 여러가지 문제가 발생할 수 있습니다. 이러한 문제를 해결하기 위해서는 프로그램 최종 사용자나 타임아웃시 Command 객체의 Cancel() 메소드를 호출함으로서 비동기 처리자체를 취소하도록 해야 합니다.

Cancel() 메소드는 어떠한 값도 반환하지 않고 비동기처리 동작을 취소하지만 이미 Command 객체에 의해 실행된 query 동작은 되돌릴 수 없습니다. 때문에 롤백(roll back)과정이 필요한 작업이라면 query 실행전 transaction 을 사용하는등의 조치가 있어야 합니다.

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

[ASP.NET] 사용자 정의 컨트롤  (0) 2016.07.21
[ASP.NET] 가장 (impersonation)  (0) 2016.07.12
[ASP.NET] ADO.NET 의 비동기 처리  (0) 2016.07.05
[C#] FtpWebRequest / FtpWebResponse  (0) 2016.06.29
[ASP.NET] SqlDataAdapter  (0) 2016.06.14
[C#] FileInfo  (1) 2016.06.09
0 0
Programming/.NET
Command 객체는 Connection 객체를 통해 연결된 DB 데이터를 다루기 위해 쿼리 또는 저장프로시저등과 같은 명령를 실행하는데 사용됩니다. 예를 들어 특정 데이터를 얻기 위한 Select 등의 쿼리는 그 결과로 DataSet 이나 DataReader 객체등의 형식과 같은 결과집합을 얻게 합니다.

Command 객체에서 주로 사용되는 속성은 다음과 같습니다.

 CommandText  일반적인 쿼리나 저장프로시저호출등의 실질적인 쿼리구문을 설정합니다.
 CommandTimeout  CommandText 에 설정된 쿼리를 실행하는데 필요한 대기시간(초)을 설정합니다. 해당 시간동안 DB서버로 부터 응답을 얻지 못하면 명령실행은 중지되며 예외를 발생시키게 됩니다. 기본값은 30초입니다.
 CommandType  CommandText 에 설정된 쿼리의 유형을 나타내거나 설정합니다.
 Connection  해당 Command 객체에 사용되는 Connection 객체를 설정합니다.

Command 객체는 실행하는 쿼리의 특성에 따라 여러 처리방법을 가지고 있으며 다음과 같은 값을 설정할 수 있습니다.

 ExecuteNonQuery  지정된 쿼리를 실행하며 해당 쿼리로 인해 영향을 받은 Row 수를 반환합니다.
 ExecuteReader  지정된 쿼리를 실행하고 그 결과로 ExecuteReader 클래스의 인스턴스를 반환합니다. 주로 Select 쿼리의 결과로 반환되는 데이터집합을 담고 있습니다.
 ExecuteRow  지정된 쿼리를 실행하고 그 결과로 SqlRecord 클래스의 인스턴스를 반환합니다. 쿼리 결과로 나오는 결과집합중 가장 첫행의 Row 값만 받을 경우 사용됩니다.
 ExecuteScalar  지정된 쿼리를 실행하고 그 결과로 Object 클래스의 인스턴스를 반환합니다. 처리결과가 Table 이나 Row 형태가 아닌 특정값 하나를 반환받을 경우 사용됩니다. 좀더 정확히는 첫 Row 의 첫 Column 의 값을 반환하는 것으로 하나 이상의 Column 이나 Row가 있다 하더라도 모두 무시됩니다.
 ExecuteXmlReader  지정된 쿼리를 실행하고 그 결과로 XmlReader 클래스의 인스턴스를 반환합니다. 주로 XML 형식의 결과를 받는데 사용됩니다.

string strCmd = "Update [Person].[PersonPhone] Set PhoneNumber = '000-000-0000' Where BusinessEntityID = 20777;";
 
SqlConnection conn = new SqlConnection(@"Data Source=localhost;Initial Catalog=AdventureWorks2012;User ID=sa;Password=123");
SqlCommand cmd = new SqlCommand(strCmd, conn);
conn.Open();
 
int updateRow = cmd.ExecuteNonQuery();
conn.Close();
▶ 예제

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

[ASP.NET] XML - 2  (0) 2016.01.26
[ASP.NET] XML - 1  (0) 2016.01.18
[ASP.NET] Command Object  (0) 2016.01.13
[ASP.NET] DLL 교체 시 웹서비스 지연현상  (0) 2015.08.07
[ASP.NET] SqlConnection  (0) 2015.05.18
[ASP.NET] IAsyncResult 인터페이스  (0) 2015.04.20
0 0
Programming/.NET
Connection 객체의 주요 목적은 데이터 소스로의 연결정보를 담는것으로 데이터소스의 도메인이나 서버 IP 및 사용자정보(아이디/비밀번호)등을 포함하고 있습니다. 흔히 이런 정보를 연결문자열이라고 부르며 문자열형태로 이루어진 데이터를 의미합니다.

Connection 객체에서 특히 SqlConnection 은 SQL Server 7.0 또는 그 상위의 MS SQL 데이터소스 작업을 위해 존재하는 클래스로서 다음과 같은 몇가지 속성을 포함하고 있습니다. 특히 ConnectionString 속성은 데이터소스 연결을 위해 필수적으로 사용해야 하는 속성입니다.

 ConnectionString  연결문자열을 설정하거나 설정된 값을 읽어옵니다.
 Database  읽기전용이며 연결된 데이터베이스 이름을 반환합니다.
 Datasource  SQL 서버 데이터 베이스의 인스턴스 이름을 반환하는 읽기전용 속성입니다.
 State  현재 연결상태를 반환하며 상태에 따라 Broken, Closed, Connecting, Executing, Fetching, Open 등의 값을 가질 수 있습니다. 읽기전용입니다.

SQL 데이터 베이스 연결을 위해서는 다음과 같은 방법으로 SqlConnection 클래스를 사용합니다.
SqlConnection conn = new SqlConnection(@"Data Source=localhost;Initial Catalog=AdventureWorks2012;User ID=sa;Password=123");
conn.Open();
▶ <코드 1-1>

<코드 1-1>에서는 SqlConnection 클래스에 대한 인스턴스를 생성하고 이와 동시에 연결문자열을 파라메터로 넘겨 초기화 합니다. 여기에서는 localhost 에 위치한 SQL Server 의 로그인을 위해 사용자 아이디와 비밀번호를 지정했는데 윈도우 계정인증을 통해 데이터 베이스에 로그인 하고자 한다면 <코드 1-2>와 같은 형태의 연결문자열을 지정해야 합니다.
@"Data Source=localhost;Initial Catalog=AdventureWorks2012;Integrated Security=True;User Instance=True"
▶ <코드 1-2>

또한 연결문자열에서 Data Source 에는 서버의 도메인이나 IP 를 지정하는 경우가 대부분 이지만 <코드 1-3>과 같이 직접 DB 파일을 지정할 수도 있습니다.
@"Data Source=.\SQLEXPRESS;AttachDbFilename=D:\DATABASE\AdventureWorks2012.MDF;Integrated Security=True;User Instance=True"
▶ <코드 1-3>

코드 1-1 에서 1-3 까지는 연결문자열을 직접 지정했는데 실제로 이렇게 하기보다는 관리성 향상과 더 높은 수준의 보안을 유지할 수 있는 Web.config 파일을 이용하는 경우가 더 많습니다.
<connectionStrings>
  <add name="new_connection" connectionString="Data Source=localhost;Initial Catalog=AdventureWorks2012;User ID=sa;Password=123" providerName="System.Data.SqlClient" />
</connectionStrings>
Web.config 파일 안에서 위와 같이 연결문자열을 지정하고난 뒤 실제 SqlConnection 안에서 Web.config 의 해당 정보를 읽어오려면 다음과 같이 처리할 수 있습니다.

SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["new_connection"].ConnectionString);
▶ <코드 1-4>

참고로 <코드 1-4>를 위해서는 System.Configuration 네임스페이스 선언이 필요합니다.

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

[ASP.NET] Command Object  (0) 2016.01.13
[ASP.NET] DLL 교체 시 웹서비스 지연현상  (0) 2015.08.07
[ASP.NET] SqlConnection  (0) 2015.05.18
[ASP.NET] IAsyncResult 인터페이스  (0) 2015.04.20
[ASP.NET] LINQ 활용  (0) 2014.10.07
[ASP.NET] DataSet  (0) 2014.10.06
0 0
Programming/.NET
.NET Framework 은 ADO.NET 과 관련한 6개의 핵심 네임스페이스를 가지고 있습니다. 더불어 몇몇 데이터 공급자는 자기 자신만의 네임스페이스를 가질 수 있는데 예를 들어 SQL Server 를 대상으로하는 .NET 데이터 공급자를 System.Data.SqlClient 에 추가하는 등의 구현이 가능합니다.

 System.Data ADO.NET 의 가장 핵심이자 상위에 속하는 네임스페이스이며 데이터공급자에 의해 사용되는 클래스와 테이블, 행, 열및 데이터셋(DataSet)등을 표현하기 위한 클래스를 포함하고 있습니다. 또한 여기에는 .NET 의 관리공급자에 의해 사용되며 ADO.NET 와 연결하기 위한 IDbCommand, IDbConnection, IDbDataAdapter 등의 인터페이스를 포함합니다.
 System.Data.Common 데이터 공급자의 기반클래스로 사용되는 공용클래스를 정의합니다. 모든 데이터 공급자는 이들 클래스를 공유하여 사용합니다.
 System.Data.OleDb  .NET OLEDB 와 관련된 데이터 처리 구현시 사용되는 클래스(OleDbConnection, OleDbCommand 포함)를 정의합니다.
 System.Data.Odbc  .NET ODBC 와 관련된 데이터 처리 구현시 사용되는 클래스(OdbcConnection, OdbcCommand 포함)를 정의합니다.
 System.Data.SqlClient  MS SQL Server 7.0 혹은 그 상위 버전을 위한 데이터 공급자를 정의합니다. 이것은 SqlConnection 과 SqlCommand 클래스를 포함하고 있습니다.
 System.Data.SqlTypes  이 네임스페이스는 SQL Server DB 의 특정 데이터타입을 표현하기 위한 클래스를 정의합니다.

ADO.NET 은 비연결, 공유, 데이터공급자인 세가지의 독특한 형식의 클래스를 가지고 있는데 우선 비연결 클래스는 ADO.NET Framework 의 기본구조를 제공하는 클래스이며 대표적인 사례로 DataTable 클래스등을 들 수 있습니다. 이 클래스의 객체는 특정 데이터 공급자에 의존하지 않고 데이터를 자체적으로 저장할 수 있습니다.

데이터 공급자의 기본 클래스인 공유클래스는 모든 데이터공급자에서 공유되는 클래스이며 마지막으로 데이터 공급자 클래스는 서로 다른 종류의 데이터 소스를 사용하는 작업을 위한 클래스입니다. 이는 특정 데이터베이스의 데이터관리를 수행하는데 사용됨을 의미하는 것으로 예를 들어 SqlClient 데이터 공급자인 경우는 (MS) SQL Server 를 대상으로 하는 데이터 공급자에 해당합니다.

또한 데이터 공급자는 Connection, Command, DataAdapter, DataReader 객체등을 포함하고 있는데 이들 객체중 Connection은 ADO.NET 작업에 있어서 가정 먼저 생성하여 DB연결을 위한 연결문자열등의 정보를 제공하는 역활을 합니다.

Command 객체는 SQL 명령에 대한 객체인데 이때 SQL 문은 일반쿼리나 저장프로시저 등의 명령일 수 있으며 필요한 경우 파라메터정보를 포함할 수 있습니다. Command 객체를 통해 SQL 문을 수행하는 경우 별다른 결과값을 받지 않는다면 단순히 쿼리를 실행하는 것으로 끝내면 되지만 그렇지 않고 결과집합(쿼리 수행 후 돌려받는 Table 형식의 결과값)등의 데이터를 받는 경우 두가지 선택적 처리방식을 결정할 수 있습니다.

첫번째로 결과집합을 데이터베이스의 연결을 유지하지 않고 계속 사용하고자 한다면 결과집합을 가지는 객체인 DataAdapter 로 부터 DataSet 이나 DataTable 객체에 결과집합을 저장해야 합니다. DataSet / DataTable 객체는 비연결상태에서도 관련 정보를 계속 유지할 수 있도록 합니다.

반면 결과집합을 한번만 처리하고 계속 유지할 필요가 없다면 단순히 DataReader 객체에서 사용자에게 데이터를 표시하고 끝낼 수 있습니다. 이것은 이전의 방법보다 좀더 빠르고 간단한 방식에 해당하지만 DataReader 객체는 데이터 소스 서버와의 연결을 계속 유지해야 하며 오직 앞으로만 순환이 가능합니다. DataRader 에 저장된 결과값을 순환해 읽기시작하면 다시 이전데이터를 읽어올 수 없으며 이 경우에는 데이터소스 서버로부터 다시 쿼리를 날려 결과집합을 가져와야 합니다. 또한 DataReader 의 결과집합은 변경할 수 없는 읽기전용 커서로서 어떤 형식으로든 변경이 필요하다면 이전에 언급한 DataSet 이나 DataTable 객체를 사용해야 합니다.

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

[ASP.NET] SqlCommand  (0) 2014.09.20
[ASP.NET] SqlParameter  (0) 2014.09.05
[ASP.NET] ADO.NET 의 네임스페이스와 클래스  (0) 2014.09.01
[ASP.NET] LinkButton  (0) 2014.08.27
[ASP.NET] DataReader  (0) 2014.08.22
[ASP.NET] 인라인 데이터 바인딩 구문  (0) 2014.08.21
0 0
Programming/.NET
ADO.NET 은 .NET Framework 1.0 부터 포함된 핵심 컴포넌트에 해당하며 오늘날 데이터에 접근할 수 있는 다양한 방법을 제시함으로써 근본적으로 데이터를 다루기 위한 여러 기능을 제공하고 있습니다.

ADO.NET 이전의 ADO 는 데이터베이스로부터 지속적으로 데이터 연결을 유지한 상태에서 필요한 데이터를 다루어야 했는데 연결상태가 계속해서 유지되어야 한다는 면은 비효휼적인 면을 드러냈고 곧 비연결상태에서도 데이터를 다룰 수 있어야 한다는 요구가 제시되었습니다.

비연결의 근본적인 동작방식은 데이터를 특정 컬렉션에 채워넣고 DB와의 연결을 끊은상태에서 컬렉션에 채워진 데이터를 다루는 것입니다. ADO.NET 의 DataSet 이 바로 그러한 역활을 수행하는데 컬렉션에 채워진 데이터는 데이터베이스와는 분리된 상태이지만 데이터내용은 물론 모든 테이블정보(열, 행, 릴레이션관한 것등)를 완벽히 유지하면서 데이터를 다룰 수 있습니다.

사실 이게 중요한데 이전 ADO 에서는 데이터를 담아두기 위한 단독적인 테이블이 필요했으며 이것은 데이터베이스의 테이블정보를 전혀 반영하지 않은 것이었습니다.

또한 ADO.NET 은 통합된 프로그래밍 모델로서 서버나 클라이언트 모두 같은 방법으로 데이터를 다룰 수 있어서 기존 ADO 보다는 좀더 나은 생산성을 기대할 수 있습니다.

 Select

데이터 소스를 연결하고 나서 단순히 데이터를 읽어오기만 하는 경우라면 간단히 DataReader 클래스를 사용할 수 있습니다.
public List<string> GetPersonPhone()
{
    string strCmd = "Select * From [Person].[PersonPhone];";
 
    SqlConnection conn = new SqlConnection(@"Data Source=localhost;Initial Catalog=AdventureWorks2012;User ID=sa;Password=123");
    SqlCommand cmd = new SqlCommand(strCmd, conn);
    conn.Open();
 
    List<string> rtn = new List<string>();                
            
    SqlDataReader SqlReader = cmd.ExecuteReader(CommandBehavior.CloseConnection);                
 
    while (SqlReader.Read())
        rtn.Add(SqlReader["PhoneNumber"].ToString());
 
    return rtn;
}
▶<코드 1-1>

<코드 1-1>은 AdventureWorks2012 DB의 Person.PersonPhone 테이블의 내용을 가져와 그 중 PhoneNumbe
r 컬럼의 데이터를 List 에 담고 반환하는 예제입니다.

DB 서버의 연결을 위해 SqlConnection 클래스의 인스턴스를 생성해 연결문자열을 지정하고 뒤이어 SqlCom
mand 객체를 생성하면서 데이터를 가져오기 위한 쿼리문과 SqlConnection 객체를 전달합니다. 여기까지 하고 나면 DB연결준비는 끝난것으로 SqlConnection 객체의 Open 함수를 호출하여 지정한 DB를 열도록 합니다.

SqlCommand 클래스가 쿼리문을 실행하는 클래스로서 ExecuteReader 메소드를 호출해 쿼리를 전달하고 반환된 SqlDataReader 객체의 Read() 메소드를 순환호출함으로서 실제 내용을 읽어오도록 합니다. 그리고 모든 데이터를 배열이나 리스트등에 담게 되면 DB와의 연결은 자동으로 닫히게 됩니다.

 Insert

Insert 는 Select 처리가 별반 다르지 않습니다. 쿼리문을 Insert 에 맞게 수정하고 Select 때의 ExecuteReader 메소드 대신에 ExecuteNonQuery 메소드를 호출하는 것이 전부입니다.
public void AddPersonPhone()
{
    string strCmd = "Insert Into [Person].[PersonPhone] Values (20777, '1 (11) 500 555-1212', 1, GETDATE());";
 
    SqlConnection conn = new SqlConnection(@"Data Source=localhost;Initial Catalog=AdventureWorks2012;User ID=sa;Password=123");
    SqlCommand cmd = new SqlCommand(strCmd, conn);
    conn.Open();
 
    cmd.ExecuteNonQuery();
    conn.Close();
}
▶<코드 2-1>

<코드 2-1> 에서는 Select 때와는 달리 데이터를 담을 수 있는 배열등이 필요없으며 단지 DB 를 Open 한 이후 쿼리를 실행하는 ExecuteNonQuery 메소드를 바로 호출합니다. 다만 필요한 작업을 수행한 이 후 Close 메소드를 호출하여 DB 연결을 닫아주도록 합니다.

 Update

Table 의 Update 는 <코드 2-1> Insert 작업에서 쿼리만 Update 구문으로 바꿔주면 됩니다. 쉽죠?
public void ModifyPersonPhone()
{
    string strCmd = "Update [Person].[PersonPhone] Set PhoneNumber = '000-000-0000' Where BusinessEntityID = 20777;";
 
    SqlConnection conn = new SqlConnection(@"Data Source=localhost;Initial Catalog=AdventureWorks2012;User ID=sa;Password=123");
    SqlCommand cmd = new SqlCommand(strCmd, conn);
    conn.Open();
 
    cmd.ExecuteNonQuery();
    conn.Close();
}
▶<코드 3-1>

참고로 ExecuteNonQuery 함수는 쿼리 실행에 적용된 Table 의 Row 수를 반환합니다. 따라서 만일 Update 로 인해 변경된 Row 수를 알아야 한다면 ExecuteNonQuery 함수호출시 다음과 같은 방법으로 결과값을 가져오면 됩니다.
int updateRow = cmd.ExecuteNonQuery();
이러한 처리 방법은 Insert 나 Delete 등에도 똑같이 적용될 수 있습니다.

 Delete

Delete 는 Insert 나 Update 와 비교해 쿼리문만 다를 뿐 모든처리과정이 같습니다.

public void delPersonPhone()
{
    string strCmd = "Delete From Person.PersonPhone Where BusinessEntityID = 20777;";
 
    SqlConnection conn = new SqlConnection(@"Data Source=localhost;Initial Catalog=AdventureWorks2012;User ID=sa;Password=123");
    SqlCommand cmd = new SqlCommand(strCmd, conn);
    conn.Open();
 
    int updateRow = cmd.ExecuteNonQuery();
    conn.Close();
}
3 0
1
블로그 이미지

클리엘