WCF에서의 DataTable 사용
우선, 다음의 토픽을 읽어보십시오.
[WCF]데이터 보내기1
; http://blog.naver.com/unbimanse?Redirect=Log&logNo=30008913599
예전에 소개해 드렸던, "
BUG: 웹 서비스에서 DataTable 사용하기"에서는 ASMX 웹 서비스에서 어떻게 DataTable을 사용하는지에 대해서 설명했는데, 이런 방식도 WCF에서는 통하지 않는다는 내용을 담고 있습니다.
자... 이제 세월이 또 지났군요. ^^
어느새 VS.NET 2008이 나왔고,
서비스 프록시 클래스를 생성할 때, 참조된 어셈블리에 있는 데이터 타입을 활용하도록 svcutil.exe가 개선이 되었습니다. (엄밀히, 이 기능은 VS.NET 2008에서 개선되었다기보다는 "svcutil.exe" 프로그램이 개선되었다고 봐야죠. Microsoft SDK 6.0A 버전에는 개선된 기능을 담고 있는 svcutil.exe가 포함되어 있습니다.)
그럼... DataTable에 대한 지원이, 좀 나아졌을까요?
확인을 위해서 기왕 테스트 하는 김에 TypedDataset / Untyped Dataset과 함께 DataTable을 함께 다뤄봤습니다.
일단, "Untyped"인 경우에는 부가적인 작업이 필요 없지만, TypedDataset을 테스트하기 위해서 다음과 같이 "DataSet1.xsd"를 만들었습니다.
그리고 다음과 같은 간단한 DataTable 구성 함수를 만들고,
private DataTable GetTestDataTable()
{
DataTable table = new DataTable();
table.Columns.Add("CustomerID", typeof(string));
table.Columns.Add("Age", typeof(int));
DataRow row = table.NewRow();
row["CustomerID"] = "myName";
row["Age"] = 16;
table.Rows.Add(row);
return table;
}
private TestLib.DataSet1.TableRootDataTable GetTestCustomDataTable()
{
TestLib.DataSet1.TableRootDataTable table = new TestLib.DataSet1.TableRootDataTable();
TestLib.DataSet1.TableRootRow row = table.NewTableRootRow();
row.CustomerID = "Customer001";
table.Rows.Add(row);
return table;
}
위의 함수를 이용해서 다음과 같이 간단한 Operation을 구성했습니다. (ServiceContract 인터페이스는 생략)
[OperationBehavior]
public DataSet GetDataSet()
{
DataSet ds = new DataSet("TestTable");
ds.Tables.Add(GetTestDataTable());
return ds;
}
[OperationBehavior]
public DataTable GetDataTable()
{
return GetTestDataTable();
}
[OperationBehavior]
public DataSet1 GetCustomDataSet()
{
DataSet1 ds = new DataSet1();
ds.TableRoot.Merge(GetTestCustomDataTable());
return ds;
}
[OperationBehavior]
public TestLib.DataSet1.TableRootDataTable GetCustomDataTable()
{
return GetTestCustomDataTable();
}
이제 서비스를 시작하고, 클라이언트 측에서 "서비스 참조"를 해봅니다. 우선, 궁금한 것은 Operation에 대한 함수 Signature가 어떻게 되었는지인데요. 오호... 훌륭하게 다음과 같이 생성되어 있습니다.
=== Reference.cs ===
public System.Data.DataTable GetDataTable() {
return base.Channel.GetDataTable();
}
public System.Data.DataSet GetDataSet() {
return base.Channel.GetDataSet();
}
public TestLib.DataSet1 GetCustomDataSet() {
return base.Channel.GetCustomDataSet();
}
public TestLib.DataSet1.TableRootDataTable GetCustomDataTable() {
return base.Channel.GetCustomDataTable();
}
짐작하시겠지만, 이렇게 코드가 생성된 데에는 "Reuse types in referenced assemblies"의 힘이 큽니다. ^^
정말 값들이 제대로 들어가 있는지 클라이언트에서도 확인을 해볼까요?
간단하게, 테이블 데이터 출력 함수를 아래와 같이 만들고,
private void OutputDataTable(DataTable dt)
{
Debug.WriteLine("=== Table Name : " + dt.TableName + " ==== ");
foreach (DataRow row in dt.Rows)
{
Debug.WriteLine(row.Field("CustomerID"));
}
}
private void OutputDataSet(DataSet ds)
{
foreach (DataTable dt in ds.Tables)
{
OutputDataTable(dt);
}
}
서비스 함수 호출을 다음과 같이 했습니다.
DataSet ds = svc.GetDataSet();
OutputDataSet(ds);
DataTable dt = svc.GetDataTable();
OutputDataTable(dt);
DataSet1 cds = svc.GetCustomDataSet();
OutputDataSet(cds);
TestLib.DataSet1.TableRootDataTable cdt = svc.GetCustomDataTable();
OutputDataTable(cdt);
결과는... 어찌되었을까요? ^^ 두말할 것도 없이 잘 나왔겠지요.
Debug Output 실행 결과:
=== Table Name : TestTable ====
myName
=== Table Name : TestTable ====
myName
=== Table Name : TableRoot ====
Customer001
=== Table Name : TableRoot ====
Customer001
[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]