Freigeben über


Abrufen von benutzerdefinierten Typdaten (USER-Defined Type, UDT) in ADO.NET

Gilt für:SQL Server

Um einen benutzerdefinierten Typ (USER-Defined Type, UDT) auf dem Client zu erstellen, muss die Assembly, die als UDT in einer SQL Server-Datenbank registriert wurde, für die Clientanwendung verfügbar sein. Die UDT-Assembly kann in dasselbe Verzeichnis gelegt werden wie die Anwendung oder in den globalen Assemblycache (GAC). Sie können auch in Ihrem Projekt einen Verweis auf die Assembly festlegen.

Anforderungen für die Verwendung von UDTs in ADO.NET

Die in SQL Server geladene Assembly und die Assembly auf dem Client müssen kompatibel sein, damit die UDT auf dem Client erstellt werden kann. Für UDTs, die mit dem Native Serialisierungsformat definiert sind, müssen die Assemblys strukturell kompatibel sein. Für Assemblys, die mit dem UserDefined-Format definiert sind, muss die Assembly auf dem Client verfügbar sein.

Sie benötigen keine Kopie der UDT-Assembly auf dem Client, um die Rohdaten aus einer UDT-Spalte in einer Tabelle abzurufen.

Hinweis

SqlClient kann ein UDT bei nicht übereinstimmenden UDT-Versionen oder anderen Problemen nicht laden. Verwenden Sie in diesem Fall regelmäßige Problembehandlungsmechanismen, um zu bestimmen, warum die Assembly, die udT enthält, von der aufrufenden Anwendung nicht gefunden werden kann. Weitere Informationen finden Sie unter Diagnosefehler mit verwalteten Debugging-Assistenten.

Zugreifen auf UDTs mit einem SqlDataReader

Ein System.Data.SqlClient.SqlDataReader kann vom Clientcode verwendet werden, um ein Resultset abzurufen, das eine UDT-Spalte enthält, die als Instanz des Objekts verfügbar gemacht wird.

Beispiel

In diesem Beispiel wird gezeigt, wie Sie mithilfe der Main-Methode ein neues SqlDataReader-Objekt erstellen. In diesem Codebeispiel werden die folgenden Aktionen ausgeführt:

  1. Die Main-Methode erstellt ein neues SqlDataReader-Objekt und ruft die Werte aus der Tabelle "Points" ab, die eine UDT-Spalte mit dem Namen "Point" aufweist.

  2. Die Point UDT macht X- und Y-Koordinaten verfügbar, die als ganze Zahlen definiert sind.

  3. Das UDT definiert eine Distance-Methode und eine GetDistanceFromXY-Methode.

  4. Der Beispielcode ruft die Werte des Primärschlüssels und der UDT-Spalten ab, um die Möglichkeiten des UDT darzustellen.

  5. Der Beispielcode ruft die methoden Point.Distance und Point.GetDistanceFromXY auf.

  6. Die Ergebnisse werden im Konsolenfenster angezeigt.

Hinweis

Die Anwendung muss bereits einen Verweis auf die UDT-Assembly aufweisen.

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

Binden von UDTs als Bytes

In einigen Fällen möchten Sie möglicherweise die Rohdaten aus der UDT-Spalte abrufen. Möglicherweise ist der Typ nicht lokal verfügbar, oder Sie möchten eine Instanz des UDT nicht instanziieren. Mithilfe der GetBytes-Methode eines SqlDataReaderkönnen Sie die unformatierten Bytes in ein Bytearray lesen. Diese Methode liest, beginnend am angegeben Pufferoffset, einen Datenstrom von Bytes aus dem angegebenen Spaltenoffset in den Puffer eines Arrays. Eine weitere Option besteht darin, eine der methoden GetSqlBytes oder GetSqlBinary zu verwenden und den gesamten Inhalt in einem einzigen Vorgang zu lesen. In beiden Fällen wird das UDT-Objekt nie instanziiert, sodass Sie keinen Verweis auf das UDT in der Clientassembly festlegen müssen.

Beispiel

In diesem Beispiel wird gezeigt, wie Sie die Point Daten als unformatierte Bytes in einem Bytearray mithilfe eines SqlDataReaderabrufen. Der Code verwendet eine System.Text.StringBuilder, um die unformatierten Bytes in eine Zeichenfolgendarstellung zu konvertieren, die im Konsolenfenster angezeigt werden soll.

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

Beispiel für die Verwendung von GetSqlBytes

In diesem Beispiel wird gezeigt, wie sie die Point Daten als unformatierte Byte in einem einzelnen Vorgang mithilfe der GetSqlBytes-Methode abrufen. Der Code verwendet eine StringBuilder, um die unformatierten Bytes in eine Zeichenfolgendarstellung zu konvertieren, die im Konsolenfenster angezeigt werden soll.

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

Arbeiten mit UDT-Parametern

UDTs können im ADO.NET-Code sowohl als Eingabe- als auch als Ausgabeparameter verwendet werden.

Verwenden von UDTs in Abfrageparametern

UDTs können beim Einrichten einer SqlParameter für ein System.Data.SqlClient.SqlCommand-Objekt als Parameterwerte verwendet werden. Die SqlDbType.Udt Enumeration eines SqlParameter-Objekts wird verwendet, um anzugeben, dass der Parameter ein UDT ist, wenn die Add-Methode für die Parameters-Auflistung aufgerufen wird. Die UdtTypeName Eigenschaft eines SqlCommand-Objekts wird verwendet, um den vollqualifizierten Namen des UDT in der Datenbank mithilfe der <database>.<schema_name>.<object_name>-Syntax anzugeben. Sie sollten den vollqualifizierten Namen verwenden, um Mehrdeutigkeit in Ihrem Code zu vermeiden.

Eine lokale Kopie der UDT-Assembly muss dem Clientprojekt zur Verfügung stehen.

Beispiel

Der Code in diesem Beispiel erstellt SqlCommand und SqlParameter Objekte zum Einfügen von Daten in eine UDT-Spalte in einer Tabelle. Der Code verwendet die SqlDbType.Udt-Aufzählung, um den Datentyp anzugeben, und die UdtTypeName-Eigenschaft des SqlParameter-Objekts, um den vollqualifizierten Namen des UDT in der Datenbank anzugeben.

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