WCF Client Inside SQL CLR

后端 未结 5 1818
借酒劲吻你
借酒劲吻你 2021-01-15 08:52

I know it\'s not supported, and I know it\'s not even a terribly good idea. But, I want to have a WCF client inside a SQL Table Valued Function.

I\'ve (seemingly) re

5条回答
  •  感情败类
    2021-01-15 09:20

    I don't quite get it, but Kev's pointer finally led me to a working state. The WCF client wrapper gives you the actual exception - instead of the CommunicationObjectFaultedException the VS2008 proxy gives you (how has this not been fixed?).

    That exception was a FileLoadException, complaining about System.ServiceModel:

    Assembly in host store has a different signature than assembly in GAC. (Exception from HRESULT: 0x80131050) See Microsoft Knowledge Base article 949080 for more information.

    Of course, KB 949080 was no help, since it still refers to SQL 2005 (as an aside, I've noticed a lot of the SQL 2008 error messages and such still refer to 2005 - you'd think they could've at least replaced the text in the error messages) and deals with problems after updating the .NET FX - which hadn't happened.

    That did make me think of 32-bit and 64-bit differences, though. My SQL 2008 server is x64 on Server 2008 x64 - and, as such, has both a C:\Windows\Microsoft.NET\Framework and a Framework64 folder. Since SQL Server is a 64 bit process, and my assembly would be hosted in process - I loaded the assemblies from the Framework64 folder, and System.IdentityModel and System.IdentityModel.Selectors from Program Files, as opposed to Program Files (x86).

    So, I tried the x86 assemblies - but trying to load System.Web gives the rather cryptic error:

    Assembly 'System.Web' references assembly 'system.web, version=2.0.0.0, culture=neutral, publickeytoken=b03f5f7f11d50a3a.', which is not present in the current database.

    Well, yeah...I guess System.Web probably does reference System.Web. Turns out, StackOverflow already has an answer to this problem. Though it doesn't make much sense, it looks like you need to load the Framework64 version of System.Web, and the regular Framework versions of everything else.

    Unfortunately, trying that solution gave me back the dreaded WCF catch all CommunicationObjectFaultedException. Annoyed by the stupidity of WCF and IDisposable, I did away with the using and Dispose call, so that I could - you know - actually see the correct exception:

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

    I then ended up with yet another FileLoadException, this time on System.Runtime.Serialization again pointing me to the useless KB 949080.

    Figuring this was yet another case of x64 weirdness, I decided that if I was going to load the Framework assemblies, I should probably also load the Program Files (x86) System.IdentityModel assemblies.

    And - what do you know...it actually worked. IntPtr.Size at runtime was 8 bytes...so I was being loaded as x64. Marking my assembly as x64 (or x86) would fail to deploy - it only worked with AnyCPU. Running corflags on the assemblies loaded showed no differences between the bitness of the x86 or x64 versions, so I really don't know what the problem is. But, the following CREATE ASSEMBLIES worked:

    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
    

    And then deploying my user assembly as AnyCPU. YMMV may on an x86 version of Sql Server.

    Boy - I'm really starting to get annoyed at the not quite ready for prime timeness of some of this stuff. I'm almost missing the simple days of C.

提交回复
热议问题