Можно ли создавать табличные методы * в пользовательском типе SQL CLR?
У меня есть UDT CLR, который значительно выиграет от табличных методов, ala xml.nodes()
:
-- nodes() example, for reference:
declare @xml xml = '<id>1</id><id>2</id><id>5</id><id>10</id>'
select c.value('.','int') as id from @xml.nodes('/id') t (c)
Мне нужно что-то подобное для моего UDT:
-- would return tuples (1, 4), (1, 5), (1, 6)....(1, 20)
declare @udt dbo.FancyType = '1.4:20'
select * from @udt.AsTable() t (c)
Есть ли у кого-нибудь опыт? Любая помощь будет принята с благодарностью. Я пробовал несколько вещей, и все они провалились. Я искал документацию и примеры и не нашел ни одного.
Да, я знаю, что могу создавать табличные значения UDF, которые принимают мой UDT в качестве параметра, но я скорее надеялся объединить все внутри одного типа, OO-style.
EDIT
Рассел Харт нашел в документации указано, что табличные методы не поддерживаются, и исправил мой синтаксис для получения ожидаемой ошибки времени выполнения (см. ниже).
В VS2010, после создания нового UDT, я добавил это в конце определения структуры:
[SqlMethod(FillRowMethodName = "GetTable_FillRow", TableDefinition = "Id INT")]
public IEnumerable GetTable()
{
ArrayList resultCollection = new ArrayList();
resultCollection.Add(1);
resultCollection.Add(2);
resultCollection.Add(3);
return resultCollection;
}
public static void GetTable_FillRow(object tableResultObj, out SqlInt32 Id)
{
Id = (int)tableResultObj;
}
Эта сборка и развертывание успешно завершена. Но затем в SSMS мы получаем ошибку времени выполнения (если не дословно):
-- needed to alias the column in the SELECT clause, rather than after the table alias.
declare @this dbo.tvm_example = ''
select t.[Id] as [ID] from @this.GetTable() as [t]
Msg 2715, Level 16, State 3, Line 2
Column, parameter, or variable #1: Cannot find data type dbo.tvm_example.
Parameter or variable '@this' has an invalid data type.
Итак, похоже, это невозможно в конце концов. И даже если бы это было возможно, вероятно, это было бы неразумно, учитывая ограничения на изменение объектов CLR в SQL Server.
Тем не менее, если кто-то знает взломы, чтобы обойти это конкретное ограничение, я подниму новую награду соответственно.
Ответы
Ответ 1
У вас есть псевдоним таблицы, но не столбцы. Попробуйте,
declare @this dbo.tvm_example = ''
select t.[Id] as [ID] from @this.GetTable() as [t]
В соответствии с документацией http://msdn.microsoft.com/en-us/library/ms131069(v=SQL.100).aspx#Y4739, это должно завершиться неудачей при другой ошибке выполнения, связанной с неправильным типом.
Класс SqlMethodAttribute наследуется от класса SqlFunctionAttribute, поэтому SqlMethodAttribute наследует поля FillRowMethodName и TableDefinition из SqlFunctionAttribute. Это означает, что можно написать табличный метод, что не так. Метод компилируется, и сборка развертывается, но ошибка в возвращаемом типе IEnumerable возникает во время выполнения со следующим сообщением: "Метод, свойство или поле" в классе "в сборке" имеет недопустимый тип возврата ".
Они могут избегать поддержки такого метода. Если вы измените сборку с помощью обновлений метода, это может вызвать проблемы с данными в столбцах UDT.
Соответствующим решением является минимальный UDT, а затем отдельный класс методов сопровождения. Это обеспечит гибкость и полнофункциональные методы.
Метод xml узлов не будет изменяться, поэтому он не будет обладать теми же ограничениями реализации.
Надеюсь, это поможет Петру и удачи.