Эффективный способ вызова встроенной функции T-SQL из .NET CLR UDF? - PullRequest
3 голосов
/ 18 февраля 2010

Из CLR UDF (синтаксис C #) возможно ли получить более или менее прямой дескриптор для встроенной функции TSql вместо пытаясь запутать его в текст ADO.NET SQL, как это?

// Programming .inside NET CLR UDF:

// Is there a more efficient way than this command?
SqlCommand cmd... = new SqlCommand( ...'SELECT EncryptByKey(@Param, @Param2...) );
cmd.Execute();

Приведенный выше текстовый способ SQL представляется неэффективным , если метод запускается несколько раз. Я полагаю, что это будет зависеть от функций интеграции SQL Server, доступных в библиотеке классов .NET Framework при создании UDF.

Возможно, это уже самое эффективное средство, доступное с точки зрения API. Я не знаю.

Использование SQL Server 2005.


Пример встроенного

Примером встроенной функции, которую я использовал и которая может служить примером, является функция EncryptByKey (..) для SQL Server.

Шифрование вызывается несколько раз для многих значений и полей в защищенной базе данных. Когда он используется, он часто используется, в отличие от некоторых других функций, которые вызываются спорадически.

Его нельзя вызвать как пользовательский UDF с dbo, потому что он не принадлежит, он является частью SQL Server.

select dbo.EncryptByKey(..) << SQL Ошибка сервера </strong>

Вместо этого его нужно назвать неквалифицированным, вот так

select EncryptByKey(..). << ОК </strong>

Было бы неплохо назвать это более эффективно, когда оно используется в ULF CLR, как описано выше, учитывая его распространенность и постоянство.

1 Ответ

1 голос
/ 19 февраля 2010

Использование SqlCommand может показаться неэффективным, но на самом деле это не так, потому что все команды выполняются в контексте соединения. Если вы не делаете это в тесном цикле (в этом случае вам, вероятно, следует подумать о редизайне UDF), издержки будут минимальными; большая часть накладных расходов, связанных с традиционным доступом к базе данных, связана с установлением соединения и прохождением по сети, ни одна из которых здесь не является проблемой.

Если вас беспокоит весь дополнительный код, который вам нужно написать, используйте вспомогательный метод:

public static TResult Execute<TResult>(SqlConnection connection, string cmdText)
{
    using (SqlCommand cmd = new SqlCommand(cmdText, connection))
    {
        return (TResult)cmd.ExecuteScalar();
    }
}

Тогда опирайтесь на это, если у вас есть особенно распространенные функции:

public static byte[] EncryptByKey(SqlConnection connection,
    string keyName, string clearText)
{
    return Execute<byte[]>(connection,
        string.Format("SELECT ENCRYPTBYKEY(KEY_GUID('{0}'), '{1}')"));
}

Попробуйте и посмотрите - если вы не делаете это тысячи раз, вы не должны заметить никакой разницы в производительности. (Также обратите внимание, что я не беспокоюсь о внедрении SQL здесь, потому что мы уже в базе данных - нет способа добраться до этого UDF из внешнего мира.)

Насколько мне известно, не будет более "эффективного" способа. Вы должны помнить, что ваша CLR UDF на самом деле не «внутри» соединения с базой данных, она работает в своем собственном домене приложений, который был введен с SqlContext, поэтому нет такого понятия, как «прямой» доступ к синтаксису SQL - вы должны фактически выполнить эти команды через контекстное соединение, и любое упрощение будет просто синтаксическим сахаром.

Если вы обнаружите, что делаете это с очень высокой частотой, тогда я бы подумал, действительно ли уместно выполнять всю работу, которую вы пытаетесь делать, из ULF CLR. Основное назначение CLR UDF - расширить функциональность, которая уже доступна в SQL Server. Если вы выполняете чрезмерный доступ к данным или выполняете чрезмерное количество команд только для того, чтобы добраться до встроенных функций, это может быть признаком того, что вы инвертировали свои зависимости, и было бы лучше написать обычный UDF, который разветвляется на несколько утилит CLR утилиты. Просто о чем подумать.

...