2017-01-06 3 views
3

Я создал простую DLL-форму 1, чтобы преобразовать строковый адрес в строку Lat/Lon, используя внутреннюю веб-службу. Код выглядит следующим образом:Неисправность Выполнение функции CLR SQL

public class GeoCodeLib 
{ 
    [SqlFunction(IsDeterministic=false)] 
    public SqlString GetLatLon(SqlString addr) 
    { 
     Geo.GeoCode gc = new Geo.GeoCode(); 
     Geo.Location loc = gc.GetLocation(addr.Value); 
     return new SqlString(string.Format("{0:N6}, {1:N6}", loc.LatLon.Latitude, loc.LatLon.Longitude)); 
    } 
} 

У меня есть целевая платформа .NET Framework 2.0. Мы используем SQL Server 2008 R2. Сборка добавлена ​​в базу данных (сборка называется GeoCodeSqlLib.dll). Мы не установили никаких прав на него.

Я не могу назвать это. Я пробовал:

select GeoCodeSqlLib.GeoCodeLib.GetLatLon('12143 Thompson Dr. Fayetteville, AR 72704') 

Это дает мне сообщение, Cannot find either column "GeoCodeSqlLib" or the user-defined function or aggregate "GeoCodeSqlLib.GeoCodeLib.GetLatLon", or the name is ambiguous.

Я пробовал:

CREATE FUNCTION GetLatLon(@amount varchar(max)) RETURNS varchar(max) 
AS EXTERNAL NAME GeoCodeSqlLib.GeoCodeLib.GetLatLon 

Это дает мне сообщение, Could not find Type 'GeoCodeLib' in assembly 'GeoCodeSqlLib'.

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

Update

Спасибо за помощь. Итак, несколько вещей:

  • Мне нужно сделать внешний доступ, чтобы получить возможность совершать вызов веб-службы .. Я не понимал, что мне нужно создать проект SQL Server. Я просто делал обычную библиотеку классов C#.
  • Итак, я создал проект SQL Server. Проект SQL Server не поддерживает ссылки на веб-службы. Я попытался добавить ссылку на свою оригинальную DLL, поэтому новая DLL проекта SQL Server выступает в качестве прокси-сервера для исходной DLL (код в моем исходном вопросе).
  • Это, однако, дает мне: Assembly 'geocodesqllib, version ...' was not found in the SQL catalog. Но я не могу добавить его в каталог, потому что ему нужен Внешний доступ, который я не могу сделать из проекта, отличного от SQL Server (это Я знаю).

Они действительно не хотят делать это легко, не так ли?

Update 2

В соответствии с моими комментариями ниже, последний вопрос, как представляется, конфигурационный файл. Он не находит настройки. Имя сервера было изменено, чтобы защитить невиновных:

<applicationSettings> 
    <GeoCodeSqlLib.Properties.Settings> 
     <setting name="GeoCodeSqlLib_ourserver_GeoCode" serializeAs="String"> 
      <value>http://ourserver/GeoCode.svc</value> 
     </setting> 
    </GeoCodeSqlLib.Properties.Settings> 
</applicationSettings> 

ошибки я получаю:

System.Configuration.SettingsPropertyNotFoundException: The settings property 'GeoCodeSqlLib_ourserver_GeoCode' was not found. 
+1

метод должен быть 'static'. –

+0

Что касается комментария, вы правы, я пропустил эту часть сообщения об ошибке. Удаление моего ответа. Благодаря! – JuanR

ответ

4

Несколько вещей:

  1. Как Йерун Mostert упоминается в комментарий к вопросу, методы SQLCLR должны быть объявлены как static.

  2. В своем заявлении CREATE FUNCTION вам необходимо использовать NVARCHAR вместо VARCHAR.SQLCLR не поддерживает VARCHAR.

  3. В вашем заявлении CREATE FUNCTION нет необходимости использовать MAX для входного параметра и типа возврата. Комбинация широты и долготы всегда будет меньше 4000 символов, и я уверен, что адрес будет также содержать менее 4000 символов. Существует определенный успех в том, что в сигнатуре присутствует только один тип данных MAX. Вам лучше сделать оба: NVARCHAR(4000).

  4. Если вы все еще получаете ошибку «не можете найти тип», то, скорее всего, у вас также есть пространство имен, которое не отображается в коде в вопросе. Синтаксис EXTERNAL NAME является:

    EXTERNAL NAME AssemblyName.[NamespaceName.ClassName].MethodName; 
    

    Так что должен закончить тем, что что-то вроде:

    CREATE FUNCTION dbo.GetLatLon(@Address NVARCHAR(4000)) 
    RETURNS NVARCHAR(4000) 
    AS EXTERNAL NAME GeoCodeSqlLib.[{namespace_name}.GeoCodeLib].GetLatLon; 
    
  5. По поводу этого заявления:

    Я нацелился .NET Framework 2.0. Мы используем SQL Server 2008 R2

    Вы можете использовать до .NET Framework версии 3.5 в 3.0 и 3.5 запуска в CLR 2.0 и SQL Server 2005, 2008 и 2008 R2 связаны с CLR 2,0 ,


Согласно UPDATE секции в вопросе:

Нет, вы не необходимости, чтобы сделать Visual Studio Проект A "Database Project", но это сделать издавая его немного легче.

Чтобы установить библиотеку GeoCodeSqlLib на номер EXTERNAL_ACCESS, вы можете сделать это через Project Properties проекта Database в Visual Studio. Вы также можете добавить WITH PERMISSION_SET = EXTERNAL_ACCESS в свой оператор CREATE ASSEMBLY, который все равно обрабатывает процесс публикации Visual Studio (обрабатывается SSDT).

Теперь для того, чтобы иметь возможность установить любую Ассамблею EXTERNAL_ACCESS (или даже UNSAFE), вам необходимо сделать следующее:

  1. Подписать Ассамблеи (также можно легко сделать в студии проекта Визуальный Свойства) и не забудьте «защитить файл ключа паролем».

  2. Создайте проект (не публиковать), чтобы он создавал DLL.

  3. В базе данных master создайте асимметричный ключ из этой DLL.

  4. Все еще в master, создайте вход с этого асимметричного ключа.

  5. Предоставить новый ключ на основе ключа EXTERNAL ACCESS ASSEMBLY.

Теперь вы можете использовать WITH PERMISSION_SET = EXTERNAL_ACCESS (в любом CREATE ASSEMBLY или ALTER ASSEMBLY заявления для любого собрания подписали с конкретным ключом), не получаю сообщение об ошибке.

Это может помочь получить более четкое представление о том, как работать с SQLCLR. Пожалуйста, смотрите серию статей, которые я пишу по этой теме на сервере Центральной SQL (бесплатная регистрация требуется, чтобы прочитать содержимое на этом сайте):

Stairway to SQLCLR

Уровень 7 в этой серии даже описан способ использования Visual Studio/SSDT для управления описанными выше шагами, чтобы автоматизировать эту работу, поскольку VS/SSDT не справляется с этим аспектом безопасности (что печально, так как это побуждает людей идти простым путем настройки базы данных на TRUSTWORTHY ON который является защитным отверстием). И моя следующая статья будет описывать еще более простой метод с использованием шаблонов T-4 в Visual Studio.


Для Update 2 раздела и дополнительные замечания по этому ответу:

  1. Поскольку есть один App домена в каждой базе данных/комбинации владельца, все сеансы выполнения кода в пределах конкретного узла будет делиться этим точным кодом и памятью. Если у вас есть статическая переменная класса (т. Е. Переменная, которая сохраняет свое значение для срока действия домена приложения), то она распределяется между всеми сеансами, что может привести к неожиданному/ненадежному поведению. По этой причине использование переменной статического класса требует, чтобы ассамблея была помечена как UNSAFE. Кроме того, вы можете иметь переменную статического класса в SAFE и EXTERNAL_ACCESS Агрегаты, если переменная помечена как readonly.

  2. Что касается конфигурационных файлов приложений, вы можете использовать их, но «приложением» в этом случае является SQL Server. Таким образом, вы всегда можете разместить данные конфигурации в файле machine.config, который является глобальным для всего процесса конкретной версии CLR (CLR 2.0 в вашем случае), или вы можете создать файл конфигурации для SQL Server, как показано в этом ответе мой, и здесь на SO:

    Does SQL Server CLR Integration support configuration files?

+0

Спасибо. Я приближаюсь, но все еще имею пару икоты. – Pete

+1

@Pete Я только что обновил дополнительную информацию, чтобы обратиться к вашему разделу ** ОБНОВЛЕНИЕ **. –

+1

Я думаю, что мы почти там, но я жду, когда мой DBA вернется и сделает последнее немного. Большое вам спасибо за вашу помощь. Я приму ответ, когда он работает. Я еще не читал вашу статью подробно, но я заметил, что пространство имен (которое немного сбило меня с толку) на самом деле не затрагивается в вашей серии. Я никогда не создавал код на C#, который не был в пространстве имен, и если бы вы не рассмотрели его в примере «CREATE FUNCTION» выше, я бы не понял этого. Я думаю, это важно отметить! – Pete

Смежные вопросы