【问题标题】:How To Match UDT T-SQL AND C# CLR Types?如何匹配 UDT T-SQL 和 C# CLR 类型?
【发布时间】:2019-04-23 08:58:46
【问题描述】:

不确定这个问题是否有意义,但我是 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:

[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 中传递一个具有多种变量类型的列表。提前致谢。

【问题讨论】:

    标签: c# sql sql-server clr sqlclr


    【解决方案1】:

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

    试试这个以获得更好的介绍:CLR User-Defined Types

    如果我以完全错误的方式解决这个问题/是否有更简单的解决方案,请告诉我。理想情况下,我将在 Person 中传递一个具有多种变量类型的列表。

    如果存储过程将成为 T-SQL 存储过程,那么最好的方法是使用用户定义的表类型/TVP(即CREATE TYPE PersonType AS TABLE...)。但由于 SQLCLR 不接受 TVP,您可以这样做:

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

    其他说明:

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

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

    【讨论】:

      猜你喜欢
      • 2011-11-02
      • 2012-08-11
      • 1970-01-01
      • 2012-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-31
      • 2018-08-25
      相关资源
      最近更新 更多