適用於:SQL Server
使用 System.Data.DataSet
和 System.Data.SqlClient.SqlDataAdapter
來擷取和修改數據,支援使用者定義型別(UDT)。
您可以使用 Transact-SQL SELECT
語句來選取 UDT 資料行值,以使用數據配接器填入數據集。 下列範例假設您已使用下列結構和一些範例數據定義 Points
數據表。 下列 Transact-SQL 語句會建立 Points
數據表,並插入幾個數據列。
CREATE TABLE dbo.Points
(
id INT PRIMARY KEY,
p Point
);
INSERT INTO dbo.Points
VALUES (1, CONVERT (Point, '1,3'));
INSERT INTO dbo.Points
VALUES (2, CONVERT (Point, '2,4'));
INSERT INTO dbo.Points
VALUES (3, CONVERT (Point, '3,5'));
INSERT INTO dbo.Points
VALUES (4, CONVERT (Point, '4,6'));
GO
下列 ADO.NET 代碼段會擷取有效的連接字串、建立新的 SqlDataAdapter
,並使用來自 Points
數據表的數據列填入 System.Data.DataTable
。
SqlDataAdapter da = new SqlDataAdapter(
"SELECT id, p FROM dbo.Points", connectionString);
DataTable datTable = new DataTable("Points");
da.Fill(datTable);
您可以使用兩種方法來更新 DataSet
中的 UDT 資料行:
提供
SqlDataAdapter
物件的自訂InsertCommand
、UpdateCommand
和DeleteCommand
物件。使用命令產生器 (
System.Data.SqlClient.SqlCommandBuilder
) 自動為您建立INSERT
、UPDATE
和DELETE
命令。 若要進行衝突偵測,請將 時間戳 數據行(別名 rowversion)新增至包含 UDT 的 SQL Server 數據表。 timestamp 數據類型可讓您對數據表中的數據列進行版本戳記,而且保證在資料庫中是唯一的。 當數據表中的值變更時,SQL Server 會自動更新受變更影響之數據列的 8 位元組二進位數。
除非基礎表中有 時間戳 數據行,否則 SqlCommandBuilder
不會考慮用於衝突偵測的 UDT。 UDT 可能或可能無法比較,因此當使用 [比較原始值] 選項來產生命令時,它們不會包含在 WHERE
子句中。
下列範例需要建立包含 Point
UDT 資料行的第二個數據表,以及 時間戳 數據行。 這兩個 數據表都用來說明如何建立自定義命令物件來更新數據,以及如何使用時間戳 數據行進行更新。 執行下列 Transact-SQL 語句來建立第二個數據表,並填入範例數據。
CREATE TABLE dbo.Points_ts
(
id INT PRIMARY KEY,
p Point,
ts TIMESTAMP
);
INSERT INTO dbo.Points_ts (id, p)
VALUES (1, CONVERT (Point, '1,3'));
INSERT INTO dbo.Points_ts (id, p)
VALUES (2, CONVERT (Point, '2,4'));
INSERT INTO dbo.Points_ts (id, p)
VALUES (3, CONVERT (Point, '3,5'));
INSERT INTO dbo.Points_ts (id, p)
VALUES (4, CONVERT (Point, '4,6'));
下列 ADO.NET 範例有兩種方法:
UserProvidedCommands
,示範如何提供InsertCommand
、UpdateCommand
和DeleteCommand
物件,以更新Points
數據表中的Point
UDT(不包含 時間戳 數據行)。CommandBuilder
,示範如何在包含 時間戳 數據行的Points_ts
數據表中使用SqlCommandBuilder
。
using System;
using System.Data;
using System.Data.SqlClient;
class Class1
{
// Retrieves the connection string
private string connString = GetConnectionString();
static void Main()
{
UserProvidedCommands();
CommandBuilder();
}
static void UserProvidedCommands()
{
// Create a new SqlDataAdapter
SqlDataAdapter da = new SqlDataAdapter(
"SELECT id, p FROM dbo.Points", connString);
// Setup the INSERT/UPDATE/DELETE commands
SqlParameter idParam;
SqlParameter pointParam;
da.InsertCommand = new SqlCommand(
"INSERT INTO dbo.Points (id, p) VALUES (@id, @p)",
da.SelectCommand.Connection);
idParam =
da.InsertCommand.Parameters.Add("@id", SqlDbType.Int);
idParam.SourceColumn = "id";
pointParam =
da.InsertCommand.Parameters.Add("@p", SqlDbType.Udt);
pointParam.SourceColumn = "p";
pointParam.UdtTypeName = "dbo.Point";
da.UpdateCommand = new SqlCommand(
"UPDATE dbo.Points SET p = @p WHERE id = @id",
da.SelectCommand.Connection);
idParam =
da.UpdateCommand.Parameters.Add("@id", SqlDbType.Int);
idParam.SourceColumn = "id";
pointParam =
da.UpdateCommand.Parameters.Add("@p", SqlDbType.Udt);
pointParam.SourceColumn = "p";
pointParam.UdtTypeName = "dbo.Point";
da.DeleteCommand = new SqlCommand(
"DELETE dbo.Points WHERE id = @id",
da.SelectCommand.Connection);
idParam =
da.DeleteCommand.Parameters.Add("@id", SqlDbType.Int);
idParam.SourceColumn = "id";
// Fill the DataTable with UDT rows
DataTable datTable = new DataTable("Points");
da.Fill(datTable);
// Display the contents of the p (Point) column
foreach (DataRow r in datTable.Rows)
{
Point p = (Point)r[1];
Console.WriteLine(
"ID: {0}, x={1}, y={1}", r[0], p.X, p.Y);
}
// Update a row if the DataTable has at least 1 row
if (datTable.Rows.Count > 0)
{
Point oldPoint = (Point)datTable.Rows[0][1];
datTable.Rows[0][1] =
new Point(oldPoint.X + 1, oldPoint.Y + 1);
}
// Delete the last row
if (datTable.Rows.Count > 0)
{
// If we have at least 1 row
datTable.Rows[1].Delete();
}
// Insert a row. This will fail if run twice
// because 100 is a primary key value.
datTable.Rows.Add(100, new Point(100, 200));
// Send the changes back to the database
da.Update(datTable);
}
static void CommandBuilder()
{
// Create a new SqlDataAdapter
SqlDataAdapter da = new SqlDataAdapter(
"SELECT id, ts, p FROM dbo.Points_ts", connString);
// Select a few rows with UDTs from the database
DataTable datTable = new DataTable("Points");
da.Fill(datTable);
// Display the contents of the p (Point) column
foreach (DataRow r in datTable.Rows)
{
Point p = (Point)r[2];
Console.WriteLine(
"ID: {0}, x={1}, y={1}", r[0], p.X, p.Y);
}
// Update a row if DataTable has at least 1 row
if (datTable.Rows.Count > 0)
{
Point oldPoint = (Point)datTable.Rows[0][2];
datTable.Rows[0][2] =
new Point(oldPoint.X + 1, oldPoint.Y + 1);
}
// Delete the last row
if (datTable.Rows.Count > 0)
{
// if we have at least 1 row
datTable.Rows[1].Delete();
}
// Insert a row. This will fail if run twice
// because 100 is a primary key value
datTable.Rows.Add(100, null, new Point(100, 200));
// Use the CommandBuilder to generate DML statements
SqlCommandBuilder bld = new SqlCommandBuilder(da);
bld.ConflictDetection = ConflictOptions.CompareRowVersion;
// Send the changes back to the database
da.Update(datTable);
}
static private string GetConnectionString()
{
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file.
return "Data Source=localhost;Initial Catalog=AdventureWorks2022;"
+ "Integrated Security=SSPI";
}
}
- 在 ADO.NET 中存取使用者定義型別