Поделиться через


Получение данных определяемого пользователем типа (UDT) в ADO.NET

Область применения:SQL Server

Чтобы создать определяемый пользователем тип (UDT) на клиенте, сборка, зарегистрированная в качестве определяемого пользователем в базе данных SQL Server, должна быть доступна клиентскому приложению. Сборку определяемого пользователем типа можно разместить в одном каталоге с приложением или в глобальном кэше сборок. Также можно задать ссылку на сборку в проекте.

Требования к использованию определяемых пользователем пользователей в ADO.NET

Сборка, загруженная в SQL Server, и сборка на клиенте должна быть совместима, чтобы UDT был создан на клиенте. Для определяемых пользователем определяемых пользователем типов с форматом сериализации Native сборки должны быть структурированы. Для сборок, определенных в формате UserDefined, сборка должна быть доступна на клиенте.

Для получения необработанных данных из столбца UDT в таблице не требуется копия сборки UDT на клиенте.

Примечание.

SqlClient может не загрузить UDT в случае несоответствия версий UDT или других проблем. В этом случае используйте обычные механизмы устранения неполадок, чтобы определить, почему сборка, содержащая определяемый пользователем объект, не может быть найдена вызывающим приложением. Дополнительные сведения см. в диагностики ошибок с помощью помощников по управляемой отладке.

Доступ к определяемым пользователем типам пользователей с помощью SqlDataReader

System.Data.SqlClient.SqlDataReader можно использовать из клиентского кода для получения результирующий набор, содержащий столбец UDT, который предоставляется в качестве экземпляра объекта.

Пример

В этом примере показано, как использовать метод Main для создания нового объекта SqlDataReader. В этом примере кода выполняются следующие действия.

  1. Метод Main создает новый объект SqlDataReader и извлекает значения из таблицы Point, которая содержит столбец UDT с именем Point.

  2. Point UDT предоставляет координаты X и Y, определенные как целые числа.

  3. UDT определяет метод Distance и метод GetDistanceFromXY.

  4. Образец кода получает значения первичного ключа и столбцов определяемого пользователем типа, чтобы продемонстрировать его возможности.

  5. Пример кода вызывает методы Point.Distance и Point.GetDistanceFromXY.

  6. Результаты выводятся в окне консоли.

Примечание.

Приложение должно содержать ссылку на сборку определяемого пользователем типа.

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. Возможно, тип недоступен локально или вы не хотите создать экземпляр определяемого пользователем типа. Необработанные байты можно считывать в массив байтов с помощью метода GetBytesSqlDataReader. Этот метод считывает поток байт с указанного смещения столбца в буфер в виде массива, начиная с указанного смещения. Другим вариантом является использование одного из методов GetSqlBytes или GetSqlBinary и чтение всего содержимого в одной операции. В любом случае объект UDT никогда не создается, поэтому не нужно задавать ссылку на определяемый пользователем объект в клиентской сборке.

Пример

В этом примере показано, как получить данные Point в виде необработанных байтов в массив байтов с помощью SqlDataReader. Код использует 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

В этом примере показано, как получить данные Point в виде необработанных байтов в одной операции с помощью метода GetSqlBytes. Код использует 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";
    }
  }
}

Работа с параметрами определяемого пользователем типа

Определяемые пользователем типы используются в коде ADO.NET как в качестве входных, так и в качестве выходных параметров.

Использование определяемых пользователем типов в параметрах запроса

Определяемые пользователем объекты можно использовать в качестве значений параметров при настройке SqlParameter для объекта System.Data.SqlClient.SqlCommand. Перечисление SqlDbType.Udt объекта SqlParameter используется для указания того, что параметр является определяемой пользователем функцией при вызове метода Add в коллекцию Parameters. Свойство UdtTypeName объекта SqlCommand используется для указания полного имени определяемого пользователя в базе данных с помощью синтаксиса <database>.<schema_name>.<object_name>. Необходимо использовать полное имя, чтобы избежать неоднозначности в коде.

Локальная копия сборки определяемого пользователем типа должна быть доступна в проекте клиента.

Пример

В этом примере код создает объекты SqlCommand и SqlParameter для вставки данных в столбец UDT в таблице. Код использует перечисление SqlDbType.Udt для указания типа данных и свойства UdtTypeName объекта SqlParameter, чтобы указать полное имя определяемого пользователем типа в базе данных.

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";
    }
  }
}