WCF Client Inside SQL CLR

Sé que no es compatible, y sé que ni siquiera es una idea terriblemente buena. Pero, quiero tener un cliente WCF dentro de una function valorada de tabla SQL.

He (aparentemente) registrado los ensamblajes correctos, pero cuando ejecuto mi cliente, obtengo un error de WCF:

 Msg 6522, nivel 16, estado 1, línea 1
 System.ServiceModel.CommunicationObjectFaultedException: 
  El object de comunicación, System.ServiceModel.ChannelFactory`1 [MyProxy.IMyService], 
  no se puede usar para la comunicación porque está en el estado Faulted.

Parece que funciona una testing fuera del server Sql, y ni siquiera veo al cliente WCF intentando establecer una connection TCP.

No estoy seguro si esto es un problema WCF o SQL CLR, ya que soy nuevo en ambos …..

Editar: entiendo que el System.ServiceModel requerido y sus innumerables ensamblajes están fuera de la list Sql CLR examinada. Sin embargo,

"Todavía se pueden invocar bibliotecas no compatibles desde sus procedimientos almacenados administrados, activadores, funciones definidas por el usuario, types definidos por el usuario y agregados definidos por el usuario. La biblioteca no compatible debe registrarse primero en la database de SQL Server, utilizando la instrucción CREATE ASSEMBLY. antes de que pueda usarse en su código. Cualquier biblioteca no admitida que esté registrada y se ejecute en el server debe ser revisada y probada para security y confiabilidad ".

Este artículo podría ayudarlo a descubrir cuál es la verdadera exception subyacente y ver qué tan fatal es:

http://jdconley.com/blog/archive/2007/08/22/wcfclientwrapper.aspx (copy de archive.org)

Como David dice correctamente , SQL CLR tiene soporte para un subset limitado de ensamblados .NET:

Bibliotecas de Framework .NET compatibles con SQL 2005
SQL 2005 CLR Integration Programming Model Restrictions

SQL 2008 soportó .NET Framework Libraries
SQL 2008 CLR Integration Programming Model Restrictions

System.Web.Services es compatible si el punto final es un service WSDL para que pueda ayudarlo a salir de un agujero. O bien, siempre puede utilizar un service web como proxy para cualquier punto final WCF que no sea un service web con el que esté tratando de hablar.

No lo entiendo del todo, pero el puntero de Kev finalmente me llevó a un estado funcional. El contenedor de clientes de WCF le brinda la exception real : en lugar de CommunicationObjectFaultedException, el proxy VS2008 le brinda (¿cómo no se ha solucionado esto?).

Esa exception fue FileLoadException, quejándose de System.ServiceModel:

El ensamblaje en la tienda principal tiene una firma diferente a la del ensamblado en GAC. (Excepción de HRESULT: 0x80131050) Consulte el artículo 949080 de Microsoft Knowledge Base para get más información.

Por supuesto, KB 949080 no fue de ayuda, ya que todavía se refiere a SQL 2005 (aparte, he notado una gran cantidad de posts de error de SQL 2008 y todavía se refieren a 2005; uno pensaría que podrían haber al less reemplazó el text en los posts de error) y trata con los problemas después de actualizar .NET FX, lo que no sucedió.

Sin embargo, eso me hizo pensar en las diferencias de 32 bits y de 64 bits. Mi server SQL 2008 es x64 en Server 2008 x64 y, como tal, tiene una carpeta C: \ Windows \ Microsoft.NET \ Framework y Framework64. Como SQL Server es un process de 64 bits, y mi ensamblado se alojaría en process, cargué los ensamblajes de la carpeta Framework64 y System.IdentityModel y System.IdentityModel.Selectors de Archivos de progtwig, a diferencia de los Archivos de progtwig (x86).

Entonces, probé los ensamblajes x86, pero al intentar cargar System.Web aparece el error críptico:

Assembly 'System.Web' hace reference al ensamblado 'system.web, version = 2.0.0.0, culture = neutral, publickeytoken = b03f5f7f11d50a3a.', Que no está presente en la database actual.

Bueno, sí … Creo que System.Web probablemente hace reference a System.Web. Resulta que StackOverflow ya tiene una respuesta a este problema. Aunque no tiene mucho sentido, parece que necesita cargar la versión de Framework64 de System.Web y las versiones normales de Framework de todo lo demás.

Desafortunadamente, intentar esa solución me devolvió la temida captura WCF de todas las CommunicationObjectFaultedException. Molesto por la estupidez de WCF e IDisposable, eliminé la llamada de uso y eliminación, para poder, ya sabes, ver la exception correcta:

 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(); } } } 

Luego terminé con otra exception FileLoadException, esta vez en System.Runtime.Serialization y me apuntó de nuevo al inútil KB 949080.

Suponiendo que esto era otro caso de rareza x64, decidí que si iba a cargar los ensamblados de Framework, probablemente también debería cargar los ensamblados System Files (x86) System.IdentityModel.

Y, ¿qué sabes … realmente funcionó. IntPtr.Size en time de ejecución tenía 8 bytes … por lo que me estaban cargando como x64. Marcar mi ensamblaje como x64 (o x86) no se implementaría, solo funcionaba con AnyCPU. Ejecutar corflags en los ensamblados cargados no mostró diferencias entre el bitness de las versiones x86 o x64, así que realmente no sé cuál es el problema. Pero, las siguientes CREATE ASSEMBLIES funcionaron:

 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 

Y luego implementar mi ensamblado de usuario como AnyCPU. YMMV puede en una versión x86 de Sql Server.

Chico – Realmente estoy empezando a molestarme por la falta de preparación para el horario de mayor audiencia de algunas de estas cosas. Casi me estoy perdiendo los días simples de C.

Al less en SQL Server 2005, solo había un puñado de ensamblajes compatibles para SQL CLR. No creo que WCF fuera uno de ellos. Hice una búsqueda rápida, y no apareció nada que me lleve a la conclusión de que mucho ha cambiado para 2008 SQL CLR.

Referencia: http://support.microsoft.com/kb/922672

Tuve problemas similares al intentar llamar a los web services de WCF dentro de SQL CLR. Carga muchos ensambles de .NET y no pude hacerlo funcionar.

Eventualmente, uso WebClient genérico para hacer una request HTTP al server WCF, que funciona muy bien y requiere min ensamblados cargados en SQL Server.

Tengo el mismo problema con el ensamblado System.Runtime.Serialization. sobre un x64 windows

La solución fue encontrar el System.Runtime.Serialization en el directory c: \ windows \ assembly, copyrlo a otro directory y ejecutar el command CREATE ASSEMBLY sql.

Mejor,