.NET 1.x 時代,DataTable 不支援序列化,無法直接作為 Web Service 回傳型別,開發者被迫使用 DataSet 甚至自訂類別包裝。ASP.NET 2.0 (NET 2.0) 徹底解決此痛點:DataTable 實作 IXmlSerializable、ISerializable,成為可獨立序列化、可直接跨服務邊界傳遞的一級資料容器。
[WebMethod]
public DataTable GetInfo() // .NET 1.1 編譯通過,執行期拋出例外
{
// ...
return custDS.Tables[0];
}
例外:System.ComponentModel.ISite 的成員 System.ComponentModel.MarshalByValueComponent.Site 是介面,因此無法將其序列化。
替代方案:回傳 DataSet(殺雞用牛刀,序列化整個 DataSet 結構)。
| 介面 | 用途 |
|---|---|
IXmlSerializable | XML 序列化自訂控制:GetSchema、ReadXml、WriteXml |
ISerializable | 二進位序列化(Remoting、BinaryFormatter) |
IListSource | GetList()、ContainsListCollection:資料繫結支援 |
.NET 1.1 僅實作 IListSource.ContainsListCollection。
[WebService(Namespace = "https://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class NorthwindService : System.Web.Services.WebService
{
[WebMethod]
public DataTable GetCustomers()
{
using (OleDbConnection conn = new OleDbConnection(
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\\Northwind\\northwind.mdb"))
using (OleDbCommand cmd = new OleDbCommand("SELECT CustomerID, CompanyName FROM Customers", conn))
using (OleDbDataAdapter da = new OleDbDataAdapter(cmd))
{
DataTable dt = new DataTable("Customers");
da.Fill(dt);
return dt; // 直接回傳,自動 XML 序列化
}
}
}
用戶端 Proxy 類別直接獲得 DataTable 型別回傳值,支援強型別存取 Rows、Columns。
private static void DemonstrateMergeTable()
{
// 建立來源資料表
DataTable table1 = new DataTable("Items");
table1.Columns.Add("id", typeof(int));
table1.Columns.Add("item", typeof(int));
table1.PrimaryKey = new DataColumn[] { table1.Columns["id"] };
for (int i = 0; i <= 3; i++)
{
DataRow row = table1.NewRow();
row["id"] = i; row["item"] = i;
table1.Rows.Add(row);
}
table1.AcceptChanges(); // 確立原始狀態
// 建立合併資料表(含新增、修改、衝突列)
DataTable table2 = table1.Clone(); // 僅複製結構
table2.Rows.Add(14, 774); // 新增
table2.Rows.Add(12, 555); // 新增
table2.Rows.Add(13, 665); // 新增
// 模擬修改既有鍵值
DataRow r = table2.NewRow(); r["id"] = 1; r["item"] = 999; table2.Rows.Add(r);
// 合併:table2 合併進 table1
table1.Merge(table2); // 預設 PreserveChanges=true,保留 table1 未認可變更
// 結果:table1 包含 id=0,1,2,3,12,13,14
// id=1 的 item 保持原值 (1) 而非 999 (因 PreserveChanges)
}
Merge(DataTable):預設 PreserveChanges=true、MissingSchemaAction=Add。Merge(DataTable, bool preserveChanges):控制是否保留目標表未認可變更。Merge(DataTable, bool preserveChanges, MissingSchemaAction):缺失結構處理(Add/Ignore/Error)。DataTable 離線編輯,重連時 Merge 伺服器最新資料。DataTable,Merge 累加至本地快取。DataTable,Merge 統一。DataTable,用戶端 Merge 至本地 DataSet。BinaryFormatter)效能優於 DataSet,適合 Remoting/內部服務通訊。NET 2.0 讓 DataTable 從「DataSet 內部元件」蛻變為「獨立可序列化、可合併、可繫結、可服務傳遞」的一級資料容器,是資料導向開發的重大里程碑。