在 ADO.NET 中擷取使用者定義型別 (UDT) 數據

適用於:SQL Server

若要在用戶端建立使用者定義型別(UDT),必須在 SQL Server 資料庫中註冊為 UDT 的組合語言可供用戶端應用程式使用。 UDT 元件可以放在與應用程式相同的目錄中,或放在全域程式集緩存 (GAC) 中。 您也可以設定專案中元件的參考。

在 ADO.NET 中使用UDT的需求

SQL Server 載入的組合語言與用戶端的組合語言必須相容,才能在用戶端建立 UDT。 對於以 Native 串行化格式定義的 UDT,元件在結構上必須相容。 對於以 UserDefined 格式定義的元件,必須在用戶端上使用元件。

你不需要在客戶端取得 UDT 組件的副本,就能從表格中的 UDT 欄位取得原始資料。

注意

SqlClient 若 UDT 版本不匹配或其他問題,可能會無法載入 UDT。 在此情況下,請使用一般疑難解答機制來判斷呼叫應用程式找不到包含UDT的元件的原因。 如需詳細資訊,請參閱 使用 Managed 偵錯小幫手診斷錯誤

本文的程式碼範例使用 Microsoft.Data.SqlClient,該套件可作為 NuGet 套件取得。 要將此依賴性加入專案,請執行以下指令:

dotnet add package Microsoft.Data.SqlClient

使用 SqlDataReader 存取 UDT

使用 Microsoft.Data.SqlClient.SqlDataReader 客戶端的程式碼取得包含 UDT 欄位的結果集,該欄位作為物件的實例被公開。

範例

這個範例示範如何使用 Main 方法來建立新的 SqlDataReader 物件。 下列動作會發生在程式代碼範例中:

  1. Main 方法會建立新的 SqlDataReader 物件,並從 Points 數據表擷取值,其具有名為 Point 的 UDT 數據行。

  2. Point UDT 會公開定義為整數的 X 和 Y 座標。

  3. UDT 會定義 Distance 方法和 GetDistanceFromXY 方法。

  4. 範例程式碼會取得主鍵與 UDT 欄位的值,以展示 UDT 的功能。

  5. 範例程式代碼會呼叫 Point.DistancePoint.GetDistanceFromXY 方法。

  6. 結果會顯示在主控台視窗中。

注意

應用程式必須已經有 UDT 元件的參考。

using System;
using Microsoft.Data.SqlClient;

namespace Microsoft.Samples.SqlServer
{
    class ReadPoints
    {
        static void Main()
        {
            string connectionString = GetConnectionString();
            using (SqlConnection cnn = new SqlConnection(connectionString))
            {
                cnn.Open();
                SqlCommand cmd = new SqlCommand(
                    "SELECT ID, Pnt FROM dbo.Points", cnn);
                SqlDataReader rdr = cmd.ExecuteReader();

                while (rdr.Read())
                {
                    // Retrieve the value of the Primary Key column
                    int id = rdr.GetInt32(0);

                    // Retrieve the value of the UDT
                    Point pnt = (Point)rdr[1];

                    // You can also use GetSqlValue and GetValue
                    // Point pnt = (Point)rdr.GetSqlValue(1);
                    // Point pnt = (Point)rdr.GetValue(1);

                    Console.WriteLine(
                        "ID={0} Point={1} X={2} Y={3} DistanceFromXY={4} Distance={5}",
                        id, pnt, pnt.X, pnt.Y, pnt.DistanceFromXY(1, 9), pnt.Distance());
                }
                rdr.Close();
                Console.WriteLine("done");
            }
            static private string GetConnectionString()
            {
                // To avoid storing the connection string in your code,
                // you can retrieve it from a configuration file.
                return "Data Source=(local);Initial Catalog=AdventureWorks2022"
                       + "Integrated Security=SSPI";
            }
        }
    }
}

將 UDT 系結為位元組

在某些情況下,您可能想要從 UDT 資料行擷取原始數據。 也許該型別在本地無法取得,或者你不想實例化 UDT。 你可以用 GetBytesSqlDataReader的方法將原始位元組讀入位元組陣列。 這個方法會從指定的數據行位移讀取位元組數據流,以從指定的緩衝區位移開始陣列的緩衝區。 另一個選項是使用其中一個 GetSqlBytesGetSqlBinary 方法,並在單一作業中讀取所有內容。 不論是哪一種情況,都永遠不會具現化 UDT 物件,因此您不需要在用戶端元件中設定 UDT 的參考。

範例

此範例展示了如何 Point 利用 SqlDataReader。 程式代碼會使用 System.Text.StringBuilder,將原始位元組轉換成要顯示在主控台視窗中的字串表示。

using System;
using Microsoft.Data.SqlClient;
using System.Data.SqlTypes;
using System.Text;

class GetRawBytes
{
    static void Main()
    {
        string connectionString = GetConnectionString();
        using (SqlConnection cnn = new SqlConnection(connectionString))
        {
            cnn.Open();
            SqlCommand cmd = new SqlCommand("SELECT ID, Pnt FROM dbo.Points", cnn);
            SqlDataReader rdr = cmd.ExecuteReader();

            while (rdr.Read())
            {
                // Retrieve the value of the Primary Key column
                int id = rdr.GetInt32(0);

                // Retrieve the raw bytes into a byte array
                byte[] buffer = new byte[32];
                long byteCount = rdr.GetBytes(1, 0, buffer, 0, 32);

                // Format and print bytes
                StringBuilder str = new StringBuilder();
                str.AppendFormat("ID={0} Point=", id);

                for (int i = 0; i < byteCount; i++)
                    str.AppendFormat("{0:x}", buffer[i]);
                Console.WriteLine(str.ToString());
            }
            rdr.Close();
            Console.WriteLine("done");
        }
    static private string GetConnectionString()
    {
        // To avoid storing the connection string in your code,
        // you can retrieve it from a configuration file.
        return "Data Source=(local);Initial Catalog=AdventureWorks2022"
            + "Integrated Security=SSPI";
    }
  }
}

使用 GetSqlBytes 的範例

此範例展示了如何利用該GetSqlBytes方法在單一操作中取得Point原始位元組資料。 程式代碼會使用 StringBuilder,將原始位元組轉換成要顯示在主控台視窗中的字串表示。

using System;
using Microsoft.Data.SqlClient;
using System.Data.SqlTypes;
using System.Text;

class GetRawBytes
{
    static void Main()
    {
         string connectionString = GetConnectionString();
        using (SqlConnection cnn = new SqlConnection(connectionString))
        {
            cnn.Open();
            SqlCommand cmd = new SqlCommand(
                "SELECT ID, Pnt FROM dbo.Points", cnn);
            SqlDataReader rdr = cmd.ExecuteReader();

            while (rdr.Read())
            {
                // Retrieve the value of the Primary Key column
                int id = rdr.GetInt32(0);

                // Use SqlBytes to retrieve raw bytes
                SqlBytes sb = rdr.GetSqlBytes(1);
                long byteCount = sb.Length;

                // Format and print bytes
                StringBuilder str = new StringBuilder();
                str.AppendFormat("ID={0} Point=", id);

                for (int i = 0; i < byteCount; i++)
                    str.AppendFormat("{0:x}", sb[i]);
                Console.WriteLine(str.ToString());
            }
            rdr.Close();
            Console.WriteLine("done");
        }
    static private string GetConnectionString()
    {
        // To avoid storing the connection string in your code,
        // you can retrieve it from a configuration file.
        return "Data Source=(local);Initial Catalog=AdventureWorks2022"
            + "Integrated Security=SSPI";
    }
  }
}

使用UDT參數

你可以在 ADO.NET 程式碼中同時使用UDT作為輸入和輸出參數。

在查詢參數中使用UDT

你可以在為物件設定 a SqlParameterMicrosoft.Data.SqlClient.SqlCommand 時,使用 UDT 作為參數值。 SqlDbType.Udt物件的列舉SqlParameter表示該參數在呼叫Add該方法到Parameters集合時為 UDT。 UdtTypeName物件的SqlCommand屬性透過語<database>.<schema_name>.<object_name>法指定資料庫中 UDT 的完全限定名稱。 使用完全限定的名稱以避免程式碼中的歧義。

用戶端項目必須使用UDT元件的本機複本。

範例

此範例中的程式代碼會建立 SqlCommandSqlParameter 物件,以將數據插入數據表中的 UDT 資料行。 程序代碼會使用 SqlDbType.Udt 列舉來指定數據類型,以及 UdtTypeName 物件的 SqlParameter 屬性,以指定資料庫中 UDT 的完整名稱。

using System;
using System.Data;
using Microsoft.Data.SqlClient;

class Class1
{
static void Main()
{
  string ConnectionString = GetConnectionString();
     using (SqlConnection cnn = new SqlConnection(ConnectionString))
     {
       SqlCommand cmd = cnn.CreateCommand();
       cmd.CommandText =
         "INSERT INTO dbo.Points (Pnt) VALUES (@Point)";
       cmd.CommandType = CommandType.Text;

       SqlParameter param = new SqlParameter("@Point", SqlDbType.Udt);       param.UdtTypeName = "TestPoint.dbo.Point";       param.Direction = ParameterDirection.Input;       param.Value = new Point(5, 6);       cmd.Parameters.Add(param);

       cnn.Open();
       cmd.ExecuteNonQuery();
       Console.WriteLine("done");
     }
    static private string GetConnectionString()
    {
        // To avoid storing the connection string in your code,
        // you can retrieve it from a configuration file.
        return "Data Source=(local);Initial Catalog=AdventureWorks2022"
            + "Integrated Security=SSPI";
    }
  }
}