Можно ли создать табличные * методы * в пользовательском типе SQL CLR? - PullRequest
12 голосов
/ 30 сентября 2011

У меня есть CLR UDT, который очень выиграл бы от табличных методов , 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.

РЕДАКТИРОВАТЬ

Рассел Харт обнаружил в документации говорится, что табличные методы не поддерживаются , и исправил мой синтаксис для получения ожидаемой ошибки времени выполнения (см. Ниже).

В 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 Ответ

8 голосов
/ 05 октября 2011

Вы создали псевдоним таблицы, но не столбцы.Попробуйте,

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 не изменится, поэтому на него не распространяются те же ограничения реализации.

Надеюсь, это поможет Петру и удачи.

...