适用范围:SQL Server
若要在客户端上创建用户定义的类型(UDT),在 SQL Server 数据库中注册为 UDT 的程序集必须可供客户端应用程序使用。 UDT 程序集可位于该应用程序的相同目录中,也可以位于全局程序集缓存 (GAC) 中。 还可以在项目中设置对该程序集的引用。
在 ADO.NET 中使用 UDT 的要求
在 SQL Server 中加载的程序集和客户端上的程序集必须与要在客户端上创建的 UDT 兼容。 对于使用 Native 序列化格式定义的 UDT,程序集必须在结构上兼容。 对于使用 UserDefined 格式定义的程序集,程序集必须在客户端上可用。
客户端上不需要 UDT 程序集的副本,才能从表中的 UDT 列检索原始数据。
注意
SqlClient 如果 UDT 版本不匹配或出现其他问题,则可能无法加载 UDT。 在这种情况下,请使用常规故障排除机制来确定调用应用程序找不到包含 UDT 的程序集的原因。 有关详细信息,请参阅 使用托管调试助手诊断错误。
本文中的代码示例使用 Microsoft.Data.SqlClient,该包可用作 NuGet 包。 若要将此依赖项添加到项目,请运行以下命令:
dotnet add package Microsoft.Data.SqlClient
使用 SqlDataReader 访问 UDT
Microsoft.Data.SqlClient.SqlDataReader使用客户端代码检索包含 UDT 列的结果集,该列作为对象的实例公开。
示例
此示例演示如何使用 Main 方法创建新的 SqlDataReader 对象。 下面的操作是在代码示例中执行的:
Main 方法创建一个新的
SqlDataReader对象,并从 Points 表中检索值,该表具有名为 Point 的 UDT 列。PointUDT 公开定义为整数的 X 和 Y 坐标。UDT 定义
Distance方法和GetDistanceFromXY方法。示例代码检索主键和 UDT 列的值,以演示 UDT 的功能。
示例代码调用
Point.Distance和Point.GetDistanceFromXY方法。结果显示在控制台窗口中。
注意
应用程序必须已具有对 UDT 程序集的引用。
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";
}
}
}
}
将 UDT 绑定为字节
在某些情况下,可能需要从 UDT 列检索原始数据。 也许类型在本地不可用,或者不想实例化 UDT 的实例。 可以使用字节数组的方法SqlDataReader将原始字节读取到字节数组GetBytes中。 该方法从指定的列偏移量将字节流作为数组从指定缓冲区偏移量开始读入缓冲区。 另一个选项是使用其中一个 GetSqlBytes 或 GetSqlBinary 方法,并在单个操作中读取所有内容。 在任一情况下,都不会实例化 UDT 对象,因此无需在客户端程序集中设置对 UDT 的引用。
示例
此示例演示如何使用 System.Text.StringBuilder 将原始字节转换为要显示在控制台窗口中的字符串表示形式。
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";
}
}
}
使用 GetSqlBytes 的示例
此示例演示如何使用GetSqlBytes该方法在单个操作中以原始字节的形式检索Point数据。 该代码使用 StringBuilder 将原始字节转换为要显示在控制台窗口中的字符串表示形式。
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";
}
}
}
使用 UDT 参数
可以在 ADO.NET 代码中使用 UDT 作为输入和输出参数。
在查询参数中使用 UDT
为对象设置 SqlParameterMicrosoft.Data.SqlClient.SqlCommand UDT 时,可以使用 UDT 作为参数值。 对象的SqlDbType.Udt枚举SqlParameter指示参数在调用AddParameters集合时是 UDT。 对象的 UdtTypeName 属性 SqlCommand 使用 <database>.<schema_name>.<object_name> 语法指定数据库中 UDT 的完全限定名称。 使用完全限定的名称避免代码中的歧义。
UDT 程序集的本地副本必须对客户端项目可用。
示例
此示例中的代码创建 SqlCommand 和 SqlParameter 对象,以将数据插入表中的 UDT 列中。 该代码使用 SqlDbType.Udt 枚举来指定数据类型,UdtTypeName 对象的 SqlParameter 属性指定数据库中 UDT 的完全限定名称。
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";
}
}
}
相关内容
- 访问 ADO.NET中的用户定义类型