如何匹配UDT T-SQL和C#CLR类型?

时间:2018-11-20 20:33:45

标签: c# sql sql-server clr sqlclr

不确定这个问题是否有意义,但是我是CLR / UDT的新手,并在此处通过以下示例完成了操作: https://docs.microsoft.com/en-us/sql/relational-databases/clr-integration/database-objects/getting-started-with-clr-integration?view=sql-server-2017

我现在想要实现的目标非常相似。我尝试添加一个字符串参数没有失败,但是添加C#对象是问题开始的地方。

这是我的C#Main:

receive

这是C#Person类:

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

我能够成功创建程序集,但这是卡住的过程。我想做类似的事情:

    public class Person
    {
        public string firstName;
        public string lastName;
        public Person(string firstName, string lastName)
        {
            this.firstName = firstName;
            this.lastName = lastName;
        }
    }

但经过一些研究,显然最好的方法是通过UDT。我遵循了另一个示例,并在T-SQL中创建了一个Person表和一个PersonType:

CREATE PROCEDURE helloname
(
    @person (@firstname nchar(300), @lastname nchar(300))
    @result nchar(300) OUTPUT
 )
AS EXTERNAL NAME helloworld.HelloWorldProc.HelloName

错误发生在这里:

CREATE TABLE Person  
(  
    FirstName nvarchar(50),  
    LastName nvarchar(50)  
)  
Go  

CREATE TYPE PersonType AS TABLE  
(  
    FirstName nvarchar(50),  
    LastName nvarchar(50)  
)  
Go  

在尝试执行时,它说“为“ helloname”创建过程失败,因为参数“ @personType”的T-SQL和CLR类型不匹配。”

如何使“ PersonType”等于C#类“ Person”以使其正常工作?让我知道我是否要以完全错误的方式进行操作/是否有更简单的解决方案。理想情况下,我将在Person内部传递具有多个变量类型的List。提前致谢。

1 个答案:

答案 0 :(得分:0)

我认为您误解了用户定义类型的概念。这些与用户定义的数据类型(将随机名称映射到实际的T-SQL数据类型)或用户定义的表类型(用于创建表变量的预定义表模式,通常用作表值参数)不同。

尝试以下方法以获得更好的介绍:CLR User-Defined Types

  

让我知道我是否要以完全错误的方式进行操作/是否有更简单的解决方案。理想情况下,我将在Person内部传递具有多个变量类型的List。

如果存储过程将是T-SQL存储过程,那么最好的方法是使用用户定义的表类型/ TVP(即CREATE TYPE PersonType AS TABLE...)。但是,由于SQLCLR不接受TVP,因此您可以执行以下任一操作:

  • 将复杂的“对象”列表构造为XML文档,可以轻松地在.NET中对其进行解析。将SqlXml用作.NET输入参数类型。
  • 创建一个本地临时表(即从单个#开始),填充它,然后使用Context Connection = true作为连接字符串在SQLCLR存储过程中从中读取它。我不确定在什么条件下该选项会比简单地传递XML文档更好/更容易,但是它仍然是一个选项。

其他说明:

  1. 您不需要param:属性的SqlFacet部分。
  2. 使用SqlString作为传入数据类型,而不是string。通过ParamName.Value属性获取.NET字符串。通过NULL属性检查ParamName.IsNull
  3. 参数不能表示为参数的组合。意思是,@person (@firstname nchar(300), @lastname nchar(300))在任何情况下都不是有效的语法。

有关一般使用SQLCLR的更多信息,请访问:SQLCLR Info