Freigeben über


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

Gilt für:SQL Server

Zum Erstellen eines benutzerdefinierten Typs (USER-Defined Type, UDT) auf dem Client muss die Assembly, die als UDT in einer SQL Server-Datenbank registriert ist, 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 das 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 nicht laden, wenn UDT-Versionen nicht übereinstimmen oder andere Probleme auftreten. 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.

Die Codebeispiele in diesem Artikel verwenden Microsoft.Data.SqlClient, die als NuGet-Paket verfügbar ist. Führen Sie zum Hinzufügen dieser Abhängigkeit zu Ihrem Projekt den folgenden Befehl aus:

dotnet add package Microsoft.Data.SqlClient

Zugreifen auf UDTs mit einem SqlDataReader

Verwenden Sie einen Microsoft.Data.SqlClient.SqlDataReader Clientcode, 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 der Primärschlüssel- und UDT-Spalten ab, um die Funktionen des UDT zu veranschaulichen.

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

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 keine Instanz des UDT instanziieren. Sie können die unformatierten Bytes in ein Bytearray lesen, indem Sie die GetBytes Methode einer SqlDataReader. 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 Die Point Daten mithilfe eines SqlDataReaderBytearrays als unformatierte Bytes in ein Bytearray abgerufen werden. 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 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";
    }
  }
}

Beispiel für die Verwendung von GetSqlBytes

In diesem Beispiel wird gezeigt, wie Die Daten mithilfe der PointGetSqlBytes Methode als unformatierte Bytes in einem einzelnen Vorgang abgerufen werden. Der Code verwendet eine StringBuilder, um die unformatierten Bytes in eine Zeichenfolgendarstellung zu konvertieren, die im Konsolenfenster angezeigt werden soll.

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

Arbeiten mit UDT-Parametern

Sie können UDTs sowohl als Eingabe- als auch als Ausgabeparameter in Ihrem ADO.NET Code verwenden.

Verwenden von UDTs in Abfrageparametern

Sie können UDTs als Parameterwerte verwenden, wenn Sie ein SqlParameterMicrosoft.Data.SqlClient.SqlCommand Objekt einrichten. Die SqlDbType.Udt Enumeration eines SqlParameter Objekts gibt an, dass der Parameter ein UDT ist, wenn die Add Methode für die Parameters Auflistung aufgerufen wird. Die UdtTypeName Eigenschaft eines SqlCommand Objekts gibt den vollqualifizierten Namen des UDT in der Datenbank mithilfe der <database>.<schema_name>.<object_name> Syntax an. Verwenden Sie den vollqualifizierten Namen, 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 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";
    }
  }
}