閱讀英文

共用方式為


使用 DataAdapters 更新使用者定義類型 (UDT) 資料行

適用於:SQL Server

使用 System.Data.DataSetSystem.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);

更新數據集中的 UDT 數據

您可以使用兩種方法來更新 DataSet中的 UDT 資料行:

  • 提供 SqlDataAdapter 物件的自訂 InsertCommandUpdateCommandDeleteCommand 物件。

  • 使用命令產生器 (System.Data.SqlClient.SqlCommandBuilder) 自動為您建立 INSERTUPDATEDELETE 命令。 若要進行衝突偵測,請將 時間戳 數據行(別名 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,示範如何提供 InsertCommandUpdateCommandDeleteCommand 物件,以更新 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";
    }
}