Клиент WCF внутри SQL CLR - PullRequest
2 голосов
/ 29 января 2009

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

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

Msg 6522, Level 16, State 1, Line 1
System.ServiceModel.CommunicationObjectFaultedException: 
 The communication object, System.ServiceModel.ChannelFactory`1[MyProxy.IMyService], 
 cannot be used for communication because it is in the Faulted state.

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

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

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

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

Ответы [ 5 ]

4 голосов
/ 29 января 2009

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

http://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, не являющейся веб-службой, с которой вы пытаетесь связаться.

3 голосов
/ 29 января 2009

Я не совсем понял, но Указатель Кева наконец привел меня в рабочее состояние. Оболочка клиента 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. Оказывается, у StackOverflow уже есть ответ на эту проблему. Хотя это не имеет особого смысла, похоже, что вам нужно загрузить версию 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.

0 голосов
/ 20 февраля 2009

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

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

Best

0 голосов
/ 29 января 2009

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

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

0 голосов
/ 29 января 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...