共用方式為


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

適用於:SQL Server

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

在 ADO.NET 中使用UDT的需求

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

您不需要用戶端上的 UDT 元件複本,即可從數據表中的 UDT 資料行擷取原始數據。

注意

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

使用 SqlDataReader 存取 UDT

您可以從用戶端程式代碼使用 System.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 System.Data.Sql;
using System.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 的實例。 您可以使用 SqlDataReaderGetBytes 方法,將原始位元組讀入位元組陣列。 這個方法會從指定的數據行位移讀取位元組數據流,以從指定的緩衝區位移開始陣列的緩衝區。 另一個選項是使用其中一個 GetSqlBytesGetSqlBinary 方法,並在單一作業中讀取所有內容。 不論是哪一種情況,都永遠不會具現化 UDT 物件,因此您不需要在用戶端元件中設定 UDT 的參考。

範例

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

using System;
using System.Data.Sql;
using System.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 System.Data.Sql;
using System.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參數

UDT 可作為 ADO.NET 程式代碼中的輸入和輸出參數。

在查詢參數中使用UDT

設定 System.Data.SqlClient.SqlCommand 物件的 SqlParameter 時,UDT 可以做為參數值。 SqlParameter 物件的 SqlDbType.Udt 列舉可用來指出參數在呼叫 Add 方法至 Parameters 集合時是 UDT。 SqlCommand 物件的 UdtTypeName 屬性是用來使用 <database>.<schema_name>.<object_name> 語法指定資料庫中 UDT 的完整名稱。 您應該使用完整名稱來避免程序代碼中的模棱兩可。

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

範例

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

using System;
using System.Data;
using System.Data.Sql;
using System.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";
    }
  }
}