不确定这个问题是否有意义,但我是 CLR/UDT 的新手,刚刚完成了这里的示例: https://learn.microsoft.com/en-us/sql/relational-databases/clr-integration/database-objects/getting-started-with-clr-integration?view=sql-server-2017
我现在想要实现的目标非常相似。我已经尝试添加一个字符串参数而没有失败,但是当添加 C# 对象时问题就开始了。
这是我的 C# 主程序:
[Microsoft.SqlServer.Server.SqlProcedure]
public static void HelloName(Person person, [param: SqlFacet(MaxSize=-1)]out string result)
{
SqlContext.Pipe.Send("Hello world!" + Environment.NewLine);
result = "Hello, " + person.firstName + " " + person.lastName;
}
这是 C# Person 类:
public class Person
{
public string firstName;
public string lastName;
public Person(string firstName, string lastName)
{
this.firstName = firstName;
this.lastName = lastName;
}
}
我能够成功创建程序集,但这是我卡住的过程。我想做类似的事情:
CREATE PROCEDURE helloname
(
@person (@firstname nchar(300), @lastname nchar(300))
@result nchar(300) OUTPUT
)
AS EXTERNAL NAME helloworld.HelloWorldProc.HelloName
但经过一些研究后,显然处理对象的最佳方法是通过 UDT。我按照另一个示例在 T-SQL 中创建了一个 Person 表和一个 PersonType,如下所示:
CREATE TABLE Person
(
FirstName nvarchar(50),
LastName nvarchar(50)
)
Go
CREATE TYPE PersonType AS TABLE
(
FirstName nvarchar(50),
LastName nvarchar(50)
)
Go
错误发生在这里:
CREATE PROCEDURE helloname
(
@personType PersonType,
@result nchar(300) OUTPUT
)
AS EXTERNAL NAME helloworld.HelloWorldProc.HelloName
在尝试执行时,它说“为“helloname”创建过程失败,因为参数“@personType”的 T-SQL 和 CLR 类型不匹配。”
如何让“PersonType”等于 C# 类“Person”才能使其正常工作?让我知道我是否以完全错误的方式解决这个问题/如果有更简单的解决方案。理想情况下,我将在 Person 中传递一个具有多个变量类型的列表。提前致谢。
最佳答案
我认为您误解了用户定义类型的概念。这些与用户定义的数据类型(将随机名称映射到实际的 T-SQL 数据类型)或用户定义的表类型(用于创建表变量的预定义表模式,通常用作表值参数)不同。
试试这个以获得更好的介绍:CLR User-Defined Types
Let me know if I'm going about this the completely wrong way/if there's a simpler solution. Ideally I will be passing in a List with multiple variable types inside Person.
如果存储过程将成为 T-SQL 存储过程,那么最好的方法是使用用户定义的表类型/TVP(即 CREATE TYPE PersonType AS TABLE...
)。但由于 SQLCLR 不接受 TVP,您可以执行以下任一操作:
- 将复杂“对象”的列表构建为 XML 文档,该文档很容易在 .NET 中进行解析。使用
SqlXml
作为 .NET 输入参数类型。 - 创建一个本地临时表(即从单个
#
开始),填充它,然后使用Context Connection = true
作为 SQLCLR 存储过程从中读取它连接字符串。我不确定在什么情况下此选项会比简单地传入 XML 文档更好/更容易,但它仍然是一个选项。
其他说明:
- 您不需要
SqlFacet
属性的param:
部分。 - 使用
SqlString
作为传入数据类型,而不是string
。通过ParamName.Value
属性获取 .NET 字符串。通过ParamName.IsNull
属性检查NULL
。 - 参数不能表示为参数的组合。意思是,
@person (@firstname nchar(300), @lastname nchar(300))
在任何情况下都不是有效语法。
有关一般使用 SQLCLR 的更多信息,请访问:SQLCLR Info
关于c# - 如何匹配 UDT T-SQL 和 C# CLR 类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53401082/