[ADO.NE강좌]닷넷 DataAdapter(OleDbDataAdapter , DataSet), FILL
닷넷 ADO.NET의 DataAdapter 는 DataSet 및 데이터 소스를 연결시키는 역할을 하며 데이터를 검색하고 저장하는 데 사용 됩니다. DataAdapter 는 DataSet에 포함된 데이터를 변경하여 데이터 소스의 데이터와 일치하도록 하는 Fill과, 데이터 소스에 포함된 데이터를 변경하여 DataSet의 데이터와 일치하도록 하는 Update를 매핑하여 이러한 연결을 제공합니다.
SQL Server 데이터베이스에 연결하는 경우, SqlDataAdapter를 관련 SqlCommand 및 SqlConnection 개체와 함께 사용하여 전반적인 성능을 향상시킬 수 있습니다.
OLE DB 지원 데이터 소스의 경우, DataAdapter를 관련 OleDbCommand 및 OleDbConnection 개체와 함께 사용합니다.
ODBC 지원 데이터 소스의 경우, DataAdapter를 관련 OdbcCommand 및 OdbcConnection 개체와 함께 사용합니다.
Oracle 데이터베이스의 경우, DataAdapter를 관련 OracleCommand 및 OracleConnection 개체와 함께 사용합니다.
이상 네가지 모두, System.Data.Common 이름 공간에 있는 추상 클래스(Abstract Class) 'DbDataAdapter'를 구현 한 것이며, 이는 같은 이름 공간의 추상 클래스 'DataAdapter' 에서 상속을 받게 되고, 추상 클래스 'DataAdapter'는 'System.Data'에 있는 IDataAdapter를 구현 한 것 입니다.
DataReader는 데이터 베이스 커넥션(Connection)을 열어, SQL 명령을 실행하고, 레코드를 열람한 후에, 더 이상의 데이터 오퍼레이션이 필요치 않으면, 마침내, 연결을 닫는 식의 순차적인 형태로 설명 될 수 있습니다.
DataAdapter는 데이터 오퍼레이션(Data Operation)이 필요한 시점에서만 데이터베이스에 연결을 해서, 필요한 조작을 하고 오퍼레이션(Operation)이 끝나면, 연결을 바로 끊는 다는 점에서, 중요한 차이점이 있습니다. 따라서, 데이터베이스 서버(Database Server) 쪽의 자원을 필요할 때만 사용한다는 점과 일정한 시점에서 동일한 서버에 저장되어 있던 동일한 여러 개의 복사본을 여러 클라이언트에서 보고, 조작하고, 다시 저장 할 수 있게 할 수 있다는 점등의 메커니즘은 매우 유용하게 응용 되어질 수 있을 것입니다.
데이터베이스에서 많은 자원을 소비하는 일중 하나가 바로 Connection을 열어두는 일이다. 개별적인 연결 하나 하나마다 많은 자원이 소비되는데 연결 수를 최소화 할 수 있다면 최소한의 부하를 일으킬 수 있는 것인데 이런 개념에서 나온 것이 바로 DataAdapter와 DataSet 입니다
특이한 부분은 DataAdapter는 데이터베이스에 종속적 이지만 DataSet은 데이터베이스에 독립적인 객체라는 점 입니다. 각각의 Provider마다 개별적인 버전의 DataAdapter가 제공되어 데이터베이스와 DataSet사이에 중계자 역할을 담당하게 되겠지만 DataSet은 데이터베이스와는 독립적이기 때문에 여러가지 버전이 존재하지 않습니다. 이는 또 여러 종류의 이질적인 데이터베이스로부터 Data를 가져와서 하나의 DataSet으로 묶을 수 있다는 것 입니다.
DataAdapter는 클라이언트가 데이터베이스에서 추출한 데이터인 DataSet과, 원본을 가지고 있는 데이터베이스 사이에서 중개자 역할을 하면서, 데이터베이스 파일과 DataSet이라는, 두 가지의 다른 포맷을 상호 전환 해주고 있다고 볼 수 있습니다.
OleDbDataAdapter public sealed class OleDbDataAdapter : DbDataAdapter,
IDbDataAdapter, IDataAdapter, ICloneable
SqlDataAdapter public sealed class SqlDataAdapter : DbDataAdapter,
IDbDataAdapter, IDataAdapter, ICloneable
DbDataAdapter public abstract class DbDataAdapter : DataAdapter
DataAdapter public abstract class DataAdapter : Component, IDataAdapter
DataAdapter
DbDataAdapter
SqlDataAdapter
OleDbDataAdapter
OdbcDataAdapter
1. OleDbDataAdapter 클래스
DataSet 을 채우고 데이터 소스를 업데이트하는 데 사용되는 데이터 명령 집합 및 데이터베이스 연결을 나타냅니다.
[OleDbDataAdapter Constructor]
OleDbDataAdapter() : OleDbDataAdapter 클래스의 새 인스턴스를 초기화합니다.
OleDbDataAdapter(OleDbCommand) : SelectCommand 속성으로서 지정된 OleDbCommand를 사용하여 OleDbDataAdapter 클래스의 새 인스턴스를 초기화합니다.
OleDbDataAdapter(String, OleDbConnection) : SelectCommand 를 사용하여 OleDbDataAdapter 클래스의 새 인스턴스를 초기화합니다.
OleDbDataAdapter(String, String) : SelectCommand 를 사용하여 OleDbDataAdapter 클래스의 새 인스턴스를 초기화합니다.
뒤의 두 컨스트럭터(Constructor)에서 인자로 받는 스트링은 OleDbCommand의 CommandType프로퍼티의 Text값을 갖는 string과, OleDbConnection 클래스의 프로퍼티(들)를 값으로 갖는 string입니다.
아래 예를 보도록 하죠.
public static OleDbDataAdapter CreateDataAdapter(
OleDbConnection connection)
{
string selectCommand =
"SELECT CustomerID, CompanyName FROM Customers";
OleDbDataAdapter adapter =
new OleDbDataAdapter(selectCommand, connection);
adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
// Create the Insert, Update and Delete commands.
adapter.InsertCommand = new OleDbCommand(
"INSERT INTO Customers (CustomerID, CompanyName) " +
"VALUES (?, ?)");
adapter.UpdateCommand = new OleDbCommand(
"UPDATE Customers SET CustomerID = ?, CompanyName = ? " +
"WHERE CustomerID = ?");
adapter.DeleteCommand = new OleDbCommand(
"DELETE FROM Customers WHERE CustomerID = ?");
// Create the parameters.
adapter.InsertCommand.Parameters.Add("@CustomerID",
OleDbType.Char, 5, "CustomerID");
adapter.InsertCommand.Parameters.Add("@CompanyName",
OleDbType.VarChar, 40, "CompanyName");
adapter.UpdateCommand.Parameters.Add("@CustomerID",
OleDbType.Char, 5, "CustomerID");
adapter.UpdateCommand.Parameters.Add("@CompanyName",
OleDbType.VarChar, 40, "CompanyName");
adapter.UpdateCommand.Parameters.Add("@oldCustomerID",
OleDbType.Char, 5, "CustomerID").SourceVersion =
DataRowVersion.Original;
adapter.DeleteCommand.Parameters.Add("@CustomerID",
OleDbType.Char, 5, "CustomerID").SourceVersion =
DataRowVersion.Original;
return adapter;
}
[OleDbDataAdapter Public Property]
AcceptChangesDuringFill : 채우기 작업을 수행하는 동안 DataTable에 추가된 DataRow에 대해 AcceptChanges가 호출되는지 여부를 나타내는 값을 가져오거나 설정합니다.
DeleteCommand : 데이터 집합에서 레코드를 삭제하는 SQL 문이나 저장 프로시저를 가져오거나 설정합니다.
public static OleDbDataAdapter CreateCustomerAdapter(
OleDbConnection connection)
{
OleDbDataAdapter dataAdapter = new OleDbDataAdapter();
OleDbCommand command;
OleDbParameter parameter;
// Create the SelectCommand.
command = new OleDbCommand("SELECT CustomerID FROM Customers " +
"WHERE Country = ? AND City = ?", connection);
command.Parameters.Add("Country", OleDbType.VarChar, 15);
command.Parameters.Add("City", OleDbType.VarChar, 15);
dataAdapter.SelectCommand = command;
// Create the DeleteCommand.
command = new OleDbCommand(
"DELETE * FROM Customers WHERE CustomerID = ?",
connection);
parameter = command.Parameters.Add(
"CustomerID", OleDbType.Char, 5, "CustomerID");
parameter.SourceVersion = DataRowVersion.Original;
dataAdapter.DeleteCommand = command;
return dataAdapter;
}
InsertCommand : 데이터 소스에 새 레코드를 삽입하는 데 사용하는 SQL 문이나 저장 프로시저를 가져오거나 설정합니다.
FillCommandBehavior: 데이터 어댑터를 채우는 데 사용되는 명령의 동작을 가져오거나 설정합니다. (DbDataAdapter에서 상속됨) public enum CommandBehavior
Default : 쿼리는 여러 결과 집합을 반환할 수 있습니다. 쿼리를 실행하면 데이터베이스 상태에 영향을 미칠 수 있습니다. Default 는 CommandBehavior 플래그를 설정하지 않으므로 ExecuteReader(CommandBehavior.Default) 호출과 ExecuteReader() 호출은 기능적으로 동일합니다.
SingleResult : 쿼리는 단일 결과 집합을 반환합니다.
SchemaOnly : 쿼리에서 열 정보만 반환합니다. SchemaOnly 를 사용할 때 .NET Framework Data Provider for SQL Server에서는 실행되는 문 앞에 SET FMTONLY ON을 배치합니다.
KeyInfo : 쿼리는 열과 기본 키 정보를 반환
SingleRow : 쿼리가 첫 번째 결과 집합의 단일 행을 반환
CloseConnection : 명령을 실행하면 관련 Connection 개체는 관련 DataReader 개체가 닫힐 때 함께 닫힙니다.
FillLoadOption 어댑터가 DbDataReader에서 DataTable을 채우는 방법을 결정하는 LoadOption을 가져오거나 설정합니다. (DataAdapter에서 상속됨) # 아래는 .NET 2.0이상에서 지원 합니다. Load 또는 Load 메서드를 사용할 때 데이터 소스의 값이 기존 행에 적용되는 방식을 제어합니다.
public enum LoadOption
OverwriteChanges : 이 행의 들어오는 값이 각 열 데이터의 현재 값 및 원래 값 버전에 작성됩니다.
PreserveChanges : 이 행의 들어오는 값이 각 열의 원래 값 버전에 작성됩니다. 각 열 데이터의 현재 버전은 변경되지 않습니다. [This] 가 기본값입니다.
Upsert : 이 행의 들어오는 값이 각 열의 현재 버전에 작성됩니다. 각 열 데이터의 원래 버전은 변경되지 않습니다.
MissingMappingAction (DataAdapter 클래스에서 상속) : 들어오는 데이터와 일치하는 테이블이나 열이 없는 경우 수행할 동작을 결정합니다.
// Assumes a valid connection string to an Access database.
static void CreateOleDbAdapter(string connectionString)
{
OleDbDataAdapter adapter = new OleDbDataAdapter();
adapter.SelectCommand =
new OleDbCommand("SELECT * FROM Categories ORDER BY CategoryID");
adapter.SelectCommand.Connection =
new OleDbConnection(connectionString);
adapter.MissingMappingAction = MissingMappingAction.Error;
adapter.MissingSchemaAction = MissingSchemaAction.Error;
}
MissingSchemaAction (DataAdapter 클래스에서 상속) : 기존 DataSet 스키마가 들어오는 데이터와 일치하지 않는 경우 수행할 동작을 결정.
SelectCommand : 데이터 소스의 레코드를 선택하는 데 사용하는 SQL 문이나 저장 프로시저를 가져오거나 설정합니다.
TableMappings (DataAdapter 클래스에서 상속) : 소스 테이블과 DataTable 사이에 마스터 매핑을 제공하는 컬렉션을 가져옵니다.TableMappingsCollection객체 발생.
public void ShowTableMappings() {
// ...
// create myDataAdapter
// ...
myDataAdapter.TableMappings.Add("Categories","DataCategories");
myDataAdapter.TableMappings.Add("Orders","DataOrders");
myDataAdapter.TableMappings.Add("Products","DataProducts");
string myMessage = "Table Mappings:\n";
for(int i=0;i < myDataAdapter.TableMappings.Count;i++) {
myMessage += i.ToString() + " "
+ myDataAdapter.TableMappings[i].ToString() + "\n";
}
MessageBox.Show(myMessage);
}
UpdateCommand :데이터 소스의 레코드를 업데이트하는 데 사용하는 SQL 문이나 저장 프로시저를 가져오거나 설정합니다.
private static OleDbDataAdapter CreateCustomerAdapter(
OleDbConnection connection)
{
OleDbDataAdapter dataAdapter = new OleDbDataAdapter();
OleDbCommand command;
OleDbParameter parameter;
// Create the SelectCommand.
command = new OleDbCommand("SELECT * FROM dbo.Customers " +
"WHERE Country = ? AND City = ?", connection);
command.Parameters.Add("Country", OleDbType.VarChar, 15);
command.Parameters.Add("City", OleDbType.VarChar, 15);
dataAdapter.SelectCommand = command;
// Create the UpdateCommand.
command = new OleDbCommand(
"UPDATE dbo.Customers SET CustomerID = ?, CompanyName = ? " +
"WHERE CustomerID = ?", connection);
command.Parameters.Add(
"CustomerID", OleDbType.Char, 5, "CustomerID");
command.Parameters.Add(
"CompanyName", OleDbType.VarChar, 40, "CompanyName");
parameter = command.Parameters.Add(
"oldCustomerID", OleDbType.Char, 5, "CustomerID");
parameter.SourceVersion = DataRowVersion.Original;
dataAdapter.UpdateCommand = command;
return dataAdapter;
}
[OleDbDataAdapter Public Method]
Fill : DbDataAdapter에 구현되어 있는 Fill() 메쏘드의 인자와 더불어 ADO Recordset, 혹은 Record 객체를 인자로서 취할 수 있는 오버로드 된 형태로, DataSet에 자료를 채움.
OleDbDataAdapter da=new OleDbDataAdapter();
OleDbDataSet ds=new OleDbDataSet();
OleDbCommand cmd=
new OleDbCommand("SELECT * FROM Name");
da.Fill(ds, "Name");
FillSchema (DbDataAdapter 클래스에서 상속) DataSet에서 한 DataTable의 스키마(Schema)를 만들어 이 스키마를 데이터 소스에 있는 스키마와 동기화 함.
OleDbCommand cmd=
new OleDbCommand("SELECT * FROM aTable);
OleDbDataAdapter da=
new OleDbDataAdapter(cmd);
DataSet ds=new DataSet();
DataTable dt=
da.FillSchema(ds, SchemaType.Source);
public static DataSet GetCustomerData(string dataSetName,
string connectionString)
{
DataSet dataSet = new DataSet(dataSetName);
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlDataAdapter adapter = new SqlDataAdapter(
"SELECT CustomerID, CompanyName, ContactName FROM dbo.Customers", connection);
DataTableMapping mapping = adapter.TableMappings.Add("Table", "Customers");
mapping.ColumnMappings.Add("CompanyName", "Name");
mapping.ColumnMappings.Add("ContactName", "Contact");
connection.Open();
adapter.FillSchema(dataSet, SchemaType.Mapped);
adapter.Fill(dataSet);
return dataSet;
}
}
GetFillParameters (DbDataAdapter 클래스에서 상속) : SQL SELECT 문을 실행할 때 사용자가 설정한 매개 변수를 가져옵니다.
OnFillError : Fill 을 수행하는 동안 오류가 발생하면 호출됩니다. (DataAdapter에서 상속됨)
[OleDbDataAdapter Events]
Disposed Dispose 메서드를 호출하여 구성 요소가 삭제되는 경우 발생합니다. (Component에서 상속됨)
FillError 채우기 작업 도중에 오류가 발생할 때 반환됩니다. (DataAdapter에서 상속됨)
RowUpdated 데이터 소스(Data Source)에 업데이트(Update)를 실행 할 경우 발생. (데이터 변경 전이라도 발생.)
RowUpdating 데이터 소스(Data Source)에 업데이트(Update)를 실행 할 경우 발생. (데이터 변경 후에만 발생.)
[예제]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.OleDb;
using System.Data;
namespace ConsoleApplication4
{
using System;
using System.Data;
using System.Data.OleDb;
class DataAdapter1
{
static void Main()
{
OleDbConnection Cn = new OleDbConnection(@"Provider=MSDAORA;data source=onj;User ID=scott;Password=tiger");
OleDbDataAdapter da = new OleDbDataAdapter();
da.SelectCommand = new OleDbCommand("select empno, ename, sal from emp", Cn);
DataSet ds = new DataSet("myFirstDataSet");
da.Fill(ds, "emp");
foreach (DataRow r in ds.Tables[0].Rows)
{
Console.WriteLine("empno : {0} ", r["empno"]);
Console.WriteLine("ename : {0} ", r["ename"]);
Console.WriteLine("sal : {0} ", r["sal"]);
}
}
}
}
[결과]
empno : 777
ename : 오라클자바
sal :
empno : 7369
ename : SMITH
sal : 800.00
empno : 7499
ename : ALLEN
sal : 1600.00
empno : 7521
................
................
................