Клиент WCF внутри SQL CLR

Я знаю, что это не поддерживается, и я знаю, что это даже не очень хорошая идея. Но я хочу иметь клиента WCF внутри функции SQL Table Valued.

Я (похоже) зарегистрировал правильные сборки, но при запуске моего клиента - я получаю ошибку WCF:

Msg 6522, уровень 16, состояние 1, строка 1
System.ServiceModel.CommunicationObjectFaultedException: 
 Объект связи, System.ServiceModel.ChannelFactory`1[MyProxy.IMyService], 
 не может быть использован для связи, потому что он находится в состоянии Failed.

Тест за пределами Sql Server, похоже, работает - и я даже не вижу, как клиент WCF пытается установить TCP-соединение.

Не уверен, что это проблема WCF или SQL CLR, так как я новичок в обоих.....

Редактировать: Я понимаю, что требуемая System.ServiceModel и ее множество сборок находятся за пределами проверенного списка Sql CLR. Тем не мение,

"Неподдерживаемые библиотеки по-прежнему можно вызывать из управляемых хранимых процедур, триггеров, пользовательских функций, пользовательских типов и пользовательских агрегатов. Неподдерживаемая библиотека сначала должна быть зарегистрирована в базе данных SQL Server с помощью оператора CREATE ASSEMBLY, прежде чем его можно будет использовать в вашем коде. Любая неподдерживаемая библиотека, которая зарегистрирована и запущена на сервере, должна быть проверена и проверена на безопасность и надежность ".

5 ответов

Решение

Эта статья может помочь вам узнать, что является истинным лежащим в основе исключением, и узнать, насколько оно фатально:

http://web.archive.org/web/20101230161606/http://www.jdconley.com/blog/archive/2007/08/22/wcfclientwrapper.aspx (копия archive.org)

Как правильно говорит Дэвид, SQL CLR поддерживает ограниченное подмножество сборок.NET:

SQL 2005 Поддерживаемые библиотеки.NET Framework
Ограничения модели программирования SQL 2005 CLR

SQL 2008 Поддерживаемые библиотеки.NET Framework
Ограничения модели программирования SQL 2008 CLR

System.Web.Services поддерживается, если конечной точкой является служба WSDL, что может помочь вам выбраться из дыры? Или вы всегда можете использовать веб-службу в качестве прокси для любой конечной точки WCF, не являющейся веб-службой, с которой вы пытаетесь связаться.

Я не совсем понимаю, но указатель Кева, наконец, привел меня в рабочее состояние. Клиентская оболочка WCF дает вам фактическое исключение - вместо CommunicationObjectFaptedException прокси-сервер VS2008 дает вам (как это не было исправлено?).

Это исключение было FileLoadException, жалуясь на System.ServiceModel:

Сборка в хост-магазине имеет другую подпись, чем сборка в GAC. (Исключение из HRESULT: 0x80131050) См. Статью 949080 базы знаний Майкрософт для получения дополнительной информации.

Конечно, KB 949080 не помог, поскольку он по-прежнему ссылается на SQL 2005 (кроме того, я заметил много сообщений об ошибках SQL 2008, и такие по-прежнему относятся к 2005 году - можно подумать, что они могли бы по крайней мере заменил текст в сообщениях об ошибках) и решает проблемы после обновления.NET FX - чего не произошло.

Это заставило меня задуматься о 32-битных и 64-битных различиях. Мой сервер SQL 2008 - x64 на сервере Server 2008 x64 - и, как таковой, имеет как папку C:\Windows\Microsoft.NET\Framework, так и папку Framework64. Поскольку SQL Server является 64-разрядным процессом, и моя сборка будет размещаться в процессе - я загрузил сборки из папки Framework64, а System.IdentityModel и System.IdentityModel.Selectors из Program Files, а не Program Files (x86).

Итак, я попробовал сборки x86 - но попытка загрузить System.Web дает довольно загадочную ошибку:

Сборка 'System.Web' ссылается на сборку 'system.web, версия =2.0.0.0, культура = нейтральная, publickeytoken=b03f5f7f11d50a3a.', Которой нет в текущей базе данных.

Ну, да... Я думаю, System.Web, вероятно, ссылается на System.Web. Оказывается, у Stackru уже есть ответ на эту проблему. Хотя это не имеет особого смысла, похоже, вам нужно загрузить версию System.Web для Framework64 и обычные версии Framework для всего остального.

К сожалению, попытка этого решения вернула мне ужасную ловушку WCF для всех CommunicationObjectFaptedException. Раздраженный глупостью WCF и IDisposable, я покончил с вызовом using и Dispose, чтобы я мог - вы знаете - действительно увидеть правильное исключение:

var p = new MyServiceClient(new CustomBinding(b), new EndpointAddress(uri));
var result = p.Execute(); // Don't Dispose proxy or you'll lose the actual exception.

try {
   return result.Values;
} finally {
   if (p.State != CommunicationState.Closed) {
      if (p.State != CommunicationState.Faulted) {
         p.Close();
      } else {
         p.Abort();
      }
   }
}

Затем я получил еще одно исключение FileLoadException, на этот раз в System.Runtime.Serialization, снова указав мне на бесполезную KB 949080.

Понимая, что это был еще один случай странности x64, я решил, что если я собираюсь загрузить сборки Framework, мне, вероятно, следует также загрузить сборки System Files.IdentityModel Program Files (x86).

И - что ты знаешь... это действительно сработало. IntPtr.Size во время выполнения был 8 байтов... поэтому я загружался как x64. Маркировка моей сборки как x64 (или x86) не удастся развернуть - она ​​работает только с AnyCPU. Запуск corflags в загруженных сборках не показал различий между разрядностью версий x86 или x64, поэтому я действительно не знаю, в чем проблема. Но, следующие CREATE ASSEMBLIES работали:

create assembly [System.Web] 
from 'C:\Windows\Microsoft.NET\Framework64\v2.0.50727\System.Web.dll'
with permission_set = UNSAFE

create assembly [System.Messaging] 
from 'C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Messaging.dll'
with permission_set = UNSAFE

create assembly [SMDiagnostics]
from 'C:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\SMDiagnostics.dll'
with permission_set = UNSAFE

CREATE ASSEMBLY [System.IdentityModel] 
from 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.0\System.IdentityModel.dll'
with permission_set = UNSAFE

CREATE ASSEMBLY [System.IdentityModel.Selectors] 
from 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.0\System.IdentityModel.Selectors.dll'
with permission_set = UNSAFE

CREATE ASSEMBLY [Microsoft.Transactions.Bridge] 
from 'C:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\Microsoft.Transactions.Bridge.dll'
with permission_set = UNSAFE

И затем развертывание моей пользовательской сборки как AnyCPU. YMMV может на x86 версии Sql Server.

Мальчик - я действительно начинаю раздражаться из-за не совсем готового к первому времени некоторых из этих вещей. Я почти пропускаю простые дни C.

У меня такая же проблема со сборкой System.Runtime.Serialization. поверх окон x64

Решением было найти System.Runtime.Serialization в каталоге c:\windows\assembly, скопировать его в другой каталог и запустить команду CREATE ASSEMBLY sql.

Лучший,

У меня были похожие проблемы при попытке вызова веб-служб WCF в SQL CLR. Он загружает столько сборок из.NET, и я не могу заставить его работать.

В конце концов, я использую универсальный WebClient для выполнения HTTP-запроса к серверу WCF, который работает очень хорошо и требует минимальных сборок, загружаемых в SQL Server.

По крайней мере, в SQL Server 2005 было только несколько поддерживаемых сборок для SQL CLR. Я не верю, что WCF был одним из них. Я сделал быстрый поиск, и ничего не помогло мне прийти к выводу, что многое изменилось в SQL CLR 2008 года.

Ссылка: http://support.microsoft.com/kb/922672

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