Передать таблицу в качестве параметра в SQLCLR TV-UDF - PullRequest
10 голосов
/ 09 июня 2010

У нас есть сторонняя DLL, которая может работать с DataTable из исходной информации и генерировать некоторые полезные значения, и мы пытаемся подключить ее через SQLCLR, чтобы она вызывалась как табличная UDF в SQL Server 2008.

Принимая концепцию здесь на шаг вперед, я хотел бы запрограммировать табличную функцию CLR , которая работает с таблицей исходных данных из БД.

Я почти уверен, что понимаю, что должно происходить на стороне T-SQL; но как должна выглядеть сигнатура метода в коде .NET (C #)? Каким будет тип данных параметра для «табличных данных из SQL Server?»

, например

/* Setup */
CREATE TYPE InTableType 
AS TABLE (LocationName VARCHAR(50), Lat FLOAT, Lon FLOAT)
GO 

CREATE TYPE OutTableType 
AS TABLE (LocationName VARCHAR(50), NeighborName VARCHAR(50), Distance FLOAT)
GO

CREATE ASSEMBLY myCLRAssembly 
FROM 'D:\assemblies\myCLR_UDFs.dll' 
WITH PERMISSION_SET = EXTERNAL_ACCESS
GO
CREATE FUNCTION GetDistances(@locations InTableType)
RETURNS OutTableType
AS 
EXTERNAL NAME myCLRAssembly.GeoDistance.SQLCLRInitMethod
GO

/* Execution */

DECLARE @myTable InTableType
INSERT INTO @myTable(LocationName, Lat, Lon) VALUES('aaa', -50.0, -20.0)
INSERT INTO @myTable(LocationName, Lat, Lon) VALUES('bbb', -20.0, -50.0)
SELECT * FROM @myTable

DECLARE @myResult OutTableType
INSERT INTO @myResult
GetDistances @myTable /* SQLCLR Call: GeoDistance.SQLCLRInitMethod(@myTable) */

Значение lat / lon -> distance - глупый пример, который, конечно, лучше обрабатывать целиком в SQL; но я надеюсь, что это иллюстрирует общее намерение «таблица в -> таблица» через табличный UDF, привязанный к сборке SQLCLR.

Я не уверен, что это возможно; как будет выглядеть сигнатура метода SQLCLRInitMethod в C #?

public class GeoDistance
{
    [SqlFunction(FillRowMethodName = "FillRow")]
    public static IEnumerable SQLCLRInitMethod(<appropriateType> myInputData)
    {
      //...
    }

    public static void FillRow(...)
    {
      //...
    }
}

Если это невозможно, я знаю, что могу использовать SQL-соединение context context = true в коде C # для запроса компонента CLR для необходимых данных с соответствующими ключами; но это чувствительно к изменениям в схеме БД. Поэтому я надеюсь, что SQL соберет все исходные данные и передаст их функции.

Бонусный вопрос - если это вообще работает, будет ли оно работать с более чем с одной таблицей ввода?

Ответы [ 2 ]

9 голосов
/ 17 июня 2010

Оказывается, что существует фиксированный список допустимых входных данных для функции SQLCLR, определяемый доступным отображением между типами данных .NET и типами данных SQL

Тип таблицы SQL "таблица" явно вызывается как имеющий отсутствие сопоставления через CLR.

Следовательно, невозможно передать табличные данные в табличную функцию CLR в качестве параметров метода.

Альтернатива

Кажется возможным получить табличные данные через select ... for xml, чтобы передать их в параметр SqlXml.

Я успешно использовал SqlConnection conn = new SqlConnection("context connection = true"); в коде .NET, чтобы позволить TVF запрашивать в БД необходимые табличные данные.

3 голосов
/ 22 января 2011

Этот вопрос (в основном) является дубликатом:

CLR Табличная функция с аргументом массива

В качестве краткого примечания, в этом вопросе ярекомендуется: список с разделителями, XML или CLR UDT.

В функции также есть возможность заполнить таблицу и загрузить из нее DataTable.Использование реальной таблицы, скорее всего, не рекомендуется, так как это потребует дополнительных усилий, чтобы сделать ее «потокобезопасной» (чтобы не пересекались данные с другими SPID), и потребует дополнительной очистки, поскольку функция не сможет выполнить DML.заявление, чтобы очистить его, как только это было сделано с данными.В определенных ситуациях, возможно, это предпочтительнее, но, вероятно, не для этого конкретного случая.К счастью, временные таблицы доступны в функциях SQLCLR (только для чтения, но вообще не доступны в функциях T-SQL).Использование временных таблиц будет иметь те же преимущества, что и использование постоянных таблиц, но не будет недостатком столкновений с другими SPID или необходимости очистки по отдельности.Единственное требование заключается в том, что вы используете контекстное соединение, так как это единственный способ доступа к объектам на основе сеанса (например, к временным таблицам).

Так что для этого конкретного случая я бы рекомендовал попробовать либо временную таблицу, либо XMLварианты.

...