Не уверен, что этот вопрос имеет смысл, но я новичок в 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. Заранее спасибо.
Я думаю, что вы неправильно поняли концепцию пользовательских типов. Это не то же самое, что определяемые пользователем типы данных (сопоставление случайного имени с фактическим типом данных T-SQL) или определяемые пользователем типы таблиц (предопределенные схемы таблиц, используемые для создания табличных переменных, обычно используемых в качестве табличных параметров).
Попробуйте это для лучшего знакомства: пользовательские типы CLR
Дайте мне знать, если я пойду по этому поводу совершенно неправильно/если есть более простое решение. В идеале я буду передавать список с несколькими типами переменных внутри Person.
Если хранимая процедура должна была быть хранимой процедурой T-SQL, то лучший способ сделать это - использовать определяемый пользователем тип таблицы /TVP (т. CREATE TYPE PersonType AS TABLE...
). Но так как SQLCLR не принимает TVP, вы можете сделать либо:
SqlXml
в качестве типа входного параметра .NET.#
), заполните ее, а затем прочитайте из нее в хранимой процедуре SQLCLR, используя Context Connection = true
в качестве строки подключения. Я не уверен, при каких условиях этот вариант будет лучше/проще, чем просто передача XML-документа, но это все же вариант.Другие заметки:
param:
часть атрибута SqlFacet
.SqlString
в качестве входящего типа данных вместо string
. Получить строку .NET через свойство ParamName.Value
. Проверьте NULL
через свойство ParamName.IsNull
.@person (@firstname nchar(300), @lastname nchar(300))
не является допустимым синтаксисом ни при каких условиях.Для получения дополнительной информации о работе с SQLCLR в целом, пожалуйста, посетите: SQLCLR Info