Пользовательский CLR SQL Server завершается с ошибкой "Не удалось загрузить файл или сборку или одну из ее зависимостей. Система не может найти указанный файл".

Я создал SQL CLR, который ссылается на Windows DLL, WindowsBase. По большей части мой CLR работает просто отлично, но если WindowsBase обновляется в GAC, я получаю сообщение об ошибке "Assembly in host store has a different signature than assembly in GAC.".

Чтобы решить эту проблему, я создал свой CLR для ссылки на версию WindowsBase, которой нет в GAC. Теперь, когда я запускаю свой CLR, я получаю ошибку "Could not load file or assembly 'WindowsBase, Version=4.0.0.0, ...' or one of its dependencies. The system cannot find the file specified."

Я настроил FusLogVw, чтобы посмотреть, что происходит, и получил следующий вывод

The system cannot find the file specified.

Assembly manager loaded from:  C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable  C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Binn\sqlservr.exe
--- A detailed error log follows. 

=== Pre-bind state information ===
    LOG: DisplayName = WindowsBase, Version=4.0.0.0
    LOG: Appbase = file:///C:/Program Files/Microsoft SQL Server/MSSQL11.MSSQLSERVER/MSSQL/Binn/
    LOG: Initial PrivatePath = NULL
    LOG: Dynamic Base = NULL
    LOG: Cache Base = NULL
    LOG: AppName = sqlservr.exe
    Calling assembly : (Unknown).
    ===
    LOG: This bind starts in default load context.
    LOG: No application configuration file found.
    LOG: Using host configuration file: 
    LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
    LOG: Post-policy reference: WindowsBase, Version=4.0.0.0
    LOG: The same bind was seen before, and was failed with hr = 0x80070002.
    ERR: Unrecoverable error occurred during pre-download check (hr = 0x80070002).

Может показаться, что загрузчик сборок использует файл machine.config, чтобы определить, где он должен искать сборку. Исходя из этого предположения, я обновил файл machine.config с помощью

<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <dependentAssembly>
             <assemblyIdentity name="WindowsBase"... />
              <codBase version="4.0.0.0"
                   href="./AdditionalAssemblies/WindowsBase.dll"/>
        </dependentAssembly>
    </assemblyBinding>
</runtime>

Я попытался с относительным путем (относительно SQlservr.exe) и абсолютным путем, но продолжаю получать ту же ошибку, упомянутую выше. Будем весьма благодарны за любые предложения о том, как настроить SQL CLR таким образом, чтобы он ссылался на копию WindowsBase, которая находится за пределами GAC, без получения указанных ошибок.

~ ~Bugz

1 ответ

Решение

То, что вы пытаетесь сделать, не поддерживается хостом CLR SQL Server. CLR в SQL Server строго ограничен, чтобы предотвратить дестабилизацию SQL Server, поскольку он работает иначе, чем приложения, работающие в ОС. Таким образом, существует очень ограниченный набор поддерживаемых библиотек DLL (т. Е. Проверенных на работу и гарантированно работающих при обновлениях.NET). WindowsBase не является одним из них, поэтому вам нужно будет загрузить его вручную, как UNSAFE в SQL Server. Но это оставляет вас либо с проблемой, с которой вы столкнулись, при изменении основного GAC (библиотеки DLL, общие для хоста CLR GAC и SQL Server, должны быть одинаковой версии), либо, что еще хуже, если DLL становится "смешанной" (как неуправляемый C++, так и управляемый код) и больше не является "чистым". В этом случае новая версия не будет загружаться, и старая версия получит ошибку "неправильная версия", так что вам есть над чем поработать.

Для получения более подробной информации, пожалуйста, смотрите следующие статьи / документацию:

Этот набор ссылок взят из раздела "Дополнительное чтение" статьи, которую я написал: Лестница к SQLCLR Уровень 5: Разработка (Использование.NET в SQL Server) (требуется бесплатная регистрация)

Другие вопросы по тегам