Как сопоставить типы UDT T-SQL и C # CLR?

2

Не уверен, что этот вопрос имеет смысл, но я новичок в CLR/UDT и только что закончил следовать этому примеру здесь: https://docs.microsoft.com/en-us/sql/relational-databases/clr-integration/database- объекты/получение стартер-с-CLR-интеграцией? вид = SQL-сервер-2017

То, чего я хочу достичь сейчас, очень похоже. Я попытался добавить в строковом параметре в обязательном порядке, но при добавлении объекта С#, где проблема начинается.

Это мой С# 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;
}

И это класс С# 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. Я последовал другому примеру и создал таблицу Person и PersonType, как показано ниже в T-SQL:

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

При попытке выполнения говорится, что "CREATE PROCEDURE for" helloname "не выполнен, так как типы T-SQL и CLR для параметра" @personType "не совпадают".

Как сделать так, чтобы "PersonType" равнялся "Person" класса С#, чтобы это работало правильно? Дайте мне знать, если я пойду по этому поводу совершенно неправильно/если есть более простое решение. В идеале я буду передавать список с несколькими типами переменных внутри Person. Заранее спасибо.

Теги:
sql-server
sqlclr
clr

1 ответ

0

Я думаю, что вы неправильно поняли концепцию пользовательских типов. Это не то же самое, что определяемые пользователем типы данных (сопоставление случайного имени с фактическим типом данных T-SQL) или определяемые пользователем типы таблиц (предопределенные схемы таблиц, используемые для создания табличных переменных, обычно используемых в качестве табличных параметров).

Попробуйте это для лучшего знакомства: пользовательские типы CLR

Дайте мне знать, если я пойду по этому поводу совершенно неправильно/если есть более простое решение. В идеале я буду передавать список с несколькими типами переменных внутри Person.

Если хранимая процедура должна была быть хранимой процедурой T-SQL, то лучший способ сделать это - использовать определяемый пользователем тип таблицы /TVP (т. CREATE TYPE PersonType AS TABLE...). Но так как SQLCLR не принимает TVP, вы можете сделать либо:

  • создать список сложных "объектов" в виде XML-документа, который легко анализируется в .NET. Используйте SqlXml в качестве типа входного параметра .NET.
  • создайте локальную временную таблицу (т.е. начинающуюся с одного #), заполните ее, а затем прочитайте из нее в хранимой процедуре SQLCLR, используя Context Connection = true в качестве строки подключения. Я не уверен, при каких условиях этот вариант будет лучше/проще, чем просто передача XML-документа, но это все же вариант.

Другие заметки:

  1. Вам не нужен param: часть атрибута SqlFacet.
  2. Используйте SqlString в качестве входящего типа данных вместо string. Получить строку .NET через свойство ParamName.Value. Проверьте NULL через свойство ParamName.IsNull.
  3. Параметры не могут быть выражены как комбинации параметров. Значение @person (@firstname nchar(300), @lastname nchar(300)) не является допустимым синтаксисом ни при каких условиях.

Для получения дополнительной информации о работе с SQLCLR в целом, пожалуйста, посетите: SQLCLR Info

Ещё вопросы

Сообщество Overcoder
Наверх
Меню