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


Получение данных определяемого пользователем типа

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

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

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

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

ПримечаниеПримечание

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

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

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

Примеры

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

  1. Метод «Main» создает новый объект SqlDataReader и получает значения от таблицы «Points», имеющей столбец определяемого пользователем типа с именем «Point».

  2. Определяемый пользователем тип «Point» представляет координаты X и Y, определенные как целые числа.

  3. Определяемый пользователем тип определяет методы Distance и GetDistanceFromXY.

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

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

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

ПримечаниеПримечание

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

Option Explicit OnOption Strict OnImports SystemImports System.Data.SqlImports System.Data.SqlClientModule ReadPoints    Sub Main()        Dim connectionString As String = GetConnectionString()        Using cnn As New SqlConnection(connectionString)            cnn.Open()            Dim cmd As New SqlCommand( _             "SELECT ID, Pnt FROM dbo.Points", cnn)            Dim rdr As SqlDataReader            rdr = cmd.ExecuteReader            While rdr.Read()                ' Retrieve the value of the Primary Key column                Dim id As Int32 = rdr.GetInt32(0)                ' Retrieve the value of the UDT                Dim pnt As Point = CType(rdr(1), Point)             ' You can also use GetSqlValue and GetValue             ' Dim pnt As Point = CType(rdr.GetSqlValue(1), Point)             ' Dim pnt As Point = CType(rdr.GetValue(1), Point)                ' Print values                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())            End While            rdr.Close()            Console.WriteLine("done")        End Using    End Sub    Private Function GetConnectionString() As String        ' To avoid storing the connection string in your code,          ' you can retrieve it from a configuration file.        Return "Data Source=(local);Initial Catalog=AdventureWorks;" _         & "Integrated Security=SSPI;"    End FunctionEnd Module
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=AdventureWorks;"        + "Integrated Security=SSPI";  }}

Привязка определяемых пользователем типов в виде байт

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

Примеры

В данном примере показано, как получать данные Point в виде необработанных байт в массиве байт с помощью SqlDataReader. В этом коде используется класс System.Text.StringBuilder для преобразования из байтового в символьное представление, применяемое для отображения в окне консоли.

Option Explicit OnOption Strict OnImports SystemImports System.Data.SqlImports System.Data.SqlClientImports System.Data.SqlTypesImports System.TextModule GetRawBytes    Sub Main()        Dim connectionString As String = GetConnectionString()        Using cnn As New SqlConnection(connectionString)            cnn.Open()            Dim cmd As New SqlCommand( _             "SELECT ID, Pnt FROM dbo.Points", cnn)            Dim rdr As SqlDataReader            rdr = cmd.ExecuteReader            While rdr.Read()                ' Retrieve the value of the Primary Key column                Dim id As Int32 = rdr.GetInt32(0)                ' Retrieve the raw bytes into a byte array                Dim buffer(31) As Byte                Dim byteCount As Integer = _                 CInt(rdr.GetBytes(1, 0, buffer, 0, 31))                ' Format and print bytes                 Dim str As New StringBuilder                str.AppendFormat("ID={0} Point=", id)                Dim i As Integer                For i = 0 To (byteCount - 1)                    str.AppendFormat("{0:x}", buffer(i))                Next                Console.WriteLine(str.ToString)            End While            rdr.Close()            Console.WriteLine("done")        End Using    End Sub    Private Function GetConnectionString() As String        ' To avoid storing the connection string in your code,          ' you can retrieve it from a configuration file.        Return "Data Source=(local);Initial Catalog=AdventureWorks;" _           & "Integrated Security=SSPI;"    End FunctionEnd Module
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=AdventureWorks;"            + "Integrated Security=SSPI";    }  }}

Пример использования GetSqlBytes

В данном примере показано, как получать данные Point в виде необработанных байт за одну операцию с помощью метода GetSqlBytes. В этом коде используется класс StringBuilder для преобразования из байтового в символьное представление, применяемое для отображения в окне консоли.

Option Explicit OnOption Strict OnImports SystemImports System.Data.SqlImports System.Data.SqlClientImports System.Data.SqlTypesImports System.TextModule GetRawBytes    Sub Main()        Dim connectionString As String = GetConnectionString()        Using cnn As New SqlConnection(connectionString)            cnn.Open()            Dim cmd As New SqlCommand( _             "SELECT ID, Pnt FROM dbo.Points", cnn)            Dim rdr As SqlDataReader            rdr = cmd.ExecuteReader            While rdr.Read()                ' Retrieve the value of the Primary Key column                Dim id As Int32 = rdr.GetInt32(0)                ' Use SqlBytes to retrieve raw bytes                Dim sb As SqlBytes = rdr.GetSqlBytes(1)                Dim byteCount As Long = sb.Length                ' Format and print bytes                 Dim str As New StringBuilder                str.AppendFormat("ID={0} Point=", id)                Dim i As Integer                For i = 0 To (byteCount - 1)                    str.AppendFormat("{0:x}", sb(i))                Next                Console.WriteLine(str.ToString)            End While            rdr.Close()            Console.WriteLine("done")        End Using    End Sub    Private Function GetConnectionString() As String        ' To avoid storing the connection string in your code,          ' you can retrieve it from a configuration file.        Return "Data Source=(local);Initial Catalog=AdventureWorks;" _           & "Integrated Security=SSPI;"    End FunctionEnd Module
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=AdventureWorks;"            + "Integrated Security=SSPI";    }  }}

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

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

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

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

ПримечаниеПримечание

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

Примеры

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

Option Explicit OnOption Strict OnImports SystemImports system.DataImports System.Data.SqlImports System.Data.SqlClientModule Module1  Sub Main()    Dim ConnectionString As String = GetConnectionString()    Dim cnn As New SqlConnection(ConnectionString)    Using cnn      Dim cmd As SqlCommand = cnn.CreateCommand()      cmd.CommandText = "INSERT INTO dbo.Points (Pnt) VALUES (@Point)"      cmd.CommandType = CommandType.Text      Dim param As 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")    End Using  End Sub    Private Function GetConnectionString() As String        ' To avoid storing the connection string in your code,          ' you can retrieve it from a configuration file.        Return "Data Source=(local);Initial Catalog=AdventureWorks;" _           & "Integrated Security=SSPI;"    End FunctionEnd Module
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=AdventureWorks;"            + "Integrated Security=SSPI";    }  }}