Исключение триггера CLR при попытке связаться со службой WCF
У меня есть CLR SQL Trigger, который пытается связаться со службой WCF на основе следующей статьи
Когда я пытаюсь обновить / вставить запись, я получаю следующее исключение:
No row was updated.
The data in row 1 was not committed.
Error Source: .Net SqlClient Data Provider.
Error Message: A .NET Framework error occured during execution of a user-defined routine or aggregate "WCFTrigger": System.Security.HostProtectionException: Attempt to perform an operation that was forbidden by the CLR host.
The protected resource (only available with full trust) where: All
The demanded resources were: Synchronization, ExternalThreading
System.Security.HostProtectionException:
at System.ServiceModel.Description.TypeLoader.LoadContractDescriptionHelper(Type ContactType, Type ServiceType, Object serviceImplementation)
at System.ServiceModel.ChannelFactory '1.CreateDescription()
at System.ServiceModel.ChannelFactory.InitializeEndpoint(Binding binding,
EndpointAddress address)
at System.ServiceModel.ChannelFactory '1..ctor(Binding binding, EndpointAddress address)
at System.ServiceModel.ClientBase '1..ctor(Binding binding, EndpointAddress address)
at ServiceClient.WCFServiceReference.ServiceContractClient..ctor(Binding binding,
EndpointAddress address)
Хост, как в статье, клиент app.config
:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IServiceContract" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None" realm=""/>
<message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8000/services/MyService" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IServiceContract" contract="WCFServiceReference.IServiceContract" name="WSHttpBinding_IServiceContract">
<identity>
<userPrincipalName value="xxx@yyy.zzzt"/>
</identity>
</endpoint>
</client>
</system.serviceModel>
<startup><supportedRuntime version="v2.0.50727"/></startup></configuration>
Кто-нибудь знает, что это и почему?
Код триггера:
public partial class Triggers {
[SqlProcedure()]
public static void SendData( String crudType ) {
EndpointAddress endpoint = new EndpointAddress( new Uri( "http://localhost:8000/services/myservice" ) );
WSHttpBinding httpBinding = new WSHttpBinding();
ServiceClient.WCFServiceReference.ServiceContractClient myClient = new ServiceClient.WCFServiceReference.ServiceContractClient( httpBinding, endpoint );
switch( crudType ) {
case "Update":
myClient.UpdateOccured();
break;
case "Insert":
myClient.InsertOccured();
break;
}
}
[Microsoft.SqlServer.Server.SqlTrigger( Name = "WCFTrigger",
Target = "tbCR", Event = "FOR UPDATE, INSERT" )]
public static void Trigger1() {
SqlTriggerContext myContext = SqlContext.TriggerContext;
switch( myContext.TriggerAction ) {
case TriggerAction.Update:
SendData( "Update" );
break;
case TriggerAction.Insert:
SendData( "Insert" );
break;
}
}
}
Прокси:
namespace ServiceClient.WCFServiceReference {
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="WCFServiceReference.IServiceContract")]
public interface IServiceContract {
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IServiceContract/UpdateOccured", ReplyAction="http://tempuri.org/IServiceContract/UpdateOccuredResponse")]
void UpdateOccured();
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IServiceContract/InsertOccured", ReplyAction="http://tempuri.org/IServiceContract/InsertOccuredResponse")]
void InsertOccured();
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public interface IServiceContractChannel : ServiceClient.WCFServiceReference.IServiceContract, System.ServiceModel.IClientChannel {
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class ServiceContractClient : System.ServiceModel.ClientBase<ServiceClient.WCFServiceReference.IServiceContract>, ServiceClient.WCFServiceReference.IServiceContract {
public ServiceContractClient() {
}
public ServiceContractClient(string endpointConfigurationName) :
base(endpointConfigurationName) {
}
public ServiceContractClient(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress) {
}
public ServiceContractClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress) {
}
public ServiceContractClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress) {
}
public void UpdateOccured() {
base.Channel.UpdateOccured();
}
public void InsertOccured() {
base.Channel.InsertOccured();
}
}
}
2 ответа
Проблема вызвана запуском кода.NET (вызывающей службы клиента WCF) в SQL Server с настройкой безопасности доступа с частичным доверительным кодом (CAS). Посмотрите на эту статью MSDN о настройке CAS для SQL Server.
РЕДАКТИРОВАТЬ:
В качестве альтернативы включению полного доверия настройте конечную точку webHttpBinding в службе WCF. Вызовите службу, используя классы System.Net HttpWebRequest и HttpWebResponse, чтобы избежать использования сантехники на основе WCF ChannelFactory.
Вы не можете делать что-либо многопоточное в любых сборках SQLCLR, и исключение говорит вам, что вы пытаетесь использовать многопоточность. Вы вызываете службу WCF асинхронно?
Я бы рекомендовал опубликовать ваш код из триггера SQLCLR для получения дополнительной помощи.
Вызов служб WCF из SQL CLR намного сложнее, чем вызов веб-служб asmx. Вы уверены, что вам нужен wcf?