Condividi tramite


Recuperare i dati di tipo definito dall'utente (UDT) in ADO.NET

Si applica a:SQL Server

Per creare un tipo definito dall'utente (UDT) nel client, l'assembly registrato come tipo definito dall'utente in un database di SQL Server deve essere disponibile per l'applicazione client. L'assembly UDT può essere posizionato nella stessa directory dell'applicazione oppure nella Global Assembly Cache (GAC). È inoltre possibile impostare un riferimento all'assembly nel progetto.

Requisiti per l'uso di tipi definiti dall'utente in ADO.NET

L'assembly caricato in SQL Server e l'assembly nel client devono essere compatibili affinché il tipo definito dall'utente venga creato nel client. Per i tipi definiti dall'utente con il formato di serializzazione Native, gli assembly devono essere compatibili strutturalmente. Per gli assembly definiti con il formato UserDefined, l'assembly deve essere disponibile nel client.

Non è necessaria una copia dell'assembly UDT nel client per recuperare i dati non elaborati da una colonna definito dall'utente in una tabella.

Nota

SqlClient potrebbe non riuscire a caricare un tipo definito dall'utente in caso di versioni definite dall'utente non corrispondenti o altri problemi. In questo caso, usare i normali meccanismi di risoluzione dei problemi per determinare il motivo per cui l'assembly contenente il tipo definito dall'utente non è stato trovato dall'applicazione chiamante. Per altre informazioni, vedere diagnosticare gli errori con assistenti di debug gestiti.

Accedere ai tipi definiti dall'utente con sqlDataReader

Un System.Data.SqlClient.SqlDataReader può essere usato dal codice client per recuperare un set di risultati contenente una colonna definita dall'utente, esposta come istanza dell'oggetto.

Esempio

In questo esempio viene illustrato come utilizzare il metodo Main per creare un nuovo oggetto SqlDataReader. All'interno del codice di esempio si verificano le azioni seguenti:

  1. Il metodo Main crea un nuovo oggetto SqlDataReader e recupera i valori dalla tabella Points, con una colonna definita dall'utente denominata Point.

  2. Il tipo definito dall'utente Point espone le coordinate X e Y definite come numeri interi.

  3. Il tipo definito dall'utente definisce un metodo Distance e un metodo GetDistanceFromXY.

  4. Il codice di esempio recupera i valori delle colonne con tipo definito dall'utente di chiave primaria per dimostrare le funzionalità del tipo definito dall'utente.

  5. Il codice di esempio chiama i metodi Point.Distance e Point.GetDistanceFromXY.

  6. I risultati vengono visualizzati nella finestra della console.

Nota

Nell'applicazione deve essere già presente un riferimento all'assembly 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";
            }
        }
    }
}

Associare tipi definiti dall'utente come byte

In alcune situazioni, potrebbe essere necessario recuperare i dati non elaborati dalla colonna definito dall'utente. Ad esempio, il tipo non è disponibile in locale o non si vuole creare un'istanza del tipo definito dall'utente. È possibile leggere i byte non elaborati in una matrice di byte usando il metodo GetBytes di un SqlDataReader. Tale metodo legge un flusso di byte dall'offset di colonna specificato nel buffer di una matrice, a partire dall'offset del buffer specificato. Un'altra opzione consiste nell'usare uno dei metodi GetSqlBytes o GetSqlBinary e leggere tutto il contenuto in una singola operazione. In entrambi i casi, l'oggetto definito dall'utente non viene mai creato un'istanza, quindi non è necessario impostare un riferimento al tipo definito dall'utente nell'assembly client.

Esempio

In questo esempio viene illustrato come recuperare i dati Point come byte non elaborati in una matrice di byte usando un SqlDataReader. Il codice usa un System.Text.StringBuilder per convertire i byte non elaborati in una rappresentazione di stringa da visualizzare nella finestra della console.

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

Esempio con GetSqlBytes

In questo esempio viene illustrato come recuperare i dati Point come byte non elaborati in una singola operazione usando il metodo GetSqlBytes. Il codice usa un StringBuilder per convertire i byte non elaborati in una rappresentazione di stringa da visualizzare nella finestra della console.

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

Usare i parametri del tipo definito dall'utente

I tipi definiti dall'utente possono essere utilizzati come parametri sia di input che di output nel codice ADO.NET.

Usare tipi definiti dall'utente nei parametri di query

I tipi definiti dall'utente possono essere usati come valori di parametro durante la configurazione di un SqlParameter per un oggetto System.Data.SqlClient.SqlCommand. L'enumerazione SqlDbType.Udt di un oggetto SqlParameter viene utilizzata per indicare che il parametro è un tipo definito dall'utente quando si chiama il metodo Add all'insieme Parameters. La proprietà UdtTypeName di un oggetto SqlCommand viene utilizzata per specificare il nome completo del tipo definito dall'utente nel database utilizzando la sintassi <database>.<schema_name>.<object_name>. È consigliabile usare il nome completo per evitare ambiguità nel codice.

Una copia locale dell'assembly UDT deve essere disponibile per il progetto client.

Esempio

Il codice in questo esempio crea SqlCommand e SqlParameter oggetti per inserire dati in una colonna definito dall'utente in una tabella. Il codice usa l'enumerazione SqlDbType.Udt per specificare il tipo di dati e la proprietà UdtTypeName dell'oggetto SqlParameter per specificare il nome completo del tipo definito dall'utente nel database.

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