在SQL CLR中访问COM

Rik*_*kki 5 c# com sqlclr user-defined-functions sql-server-2008

希望大家度过美好的一天!

我需要你对过去三天我一直在考虑的事情提出建议.我有一个用非托管平台编写的COM组件.该组件有一个返回一些敏感数据的方法,我需要在得到它后立即存储该值.

我需要的是调用UDF来访问COM对象并获取值.到目前为止我已经尝试了这个,我得到了这个例外:

消息6522,级别16,状态2,行1
在执行用户定义的例程或聚合"GetRate"期间发生.NET Framework错误:System.Runtime.InteropServices.COMException:检索具有CLSID的组件的COM类工厂{D039A99F- 5D45-42C7-A53C-507913D8C6D6}由于以下错误而失败:80040154.System.Runtime.InteropServices.COMException
:
at System.RuntimeTypeHandle.CreateInstance(RuntimeType type,Boolean publicOnly,Boolean noCheck,Boolean&canBeCached,RuntimeMethodHandle&ctor,Boolean&bNeedSecurityCheck)
在 System.RuntimeType.CreateInstanceSlow(Boolean publicOnly,Boolean fillCache)
at System.RuntimeType.CreateInstanceImpl(Boolean publicOnly,Boolean skipVisibilityChecks,Boolean fillCache)
在 System.Activator.CreateInstance(Type type,Boolean nonPublic)
at UserDefinedFunctions.GetRate(SqlString Source_Currency_Name,SqlString Destination_Currency_Name,SqlMoney Amount,SqlBoolean Mode)

似乎该功能无法看到已注册的COM组件(80040154).clr程序集注册为不受限制.我试图用'sa'或Windows集成模式调用UDF.没有区别.

这是用于初始化COM组件的代码,代码在SQL之外正常工作:

Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("D039A99F-5D45-42C7-A53C-507913D8C6D6"), true))
Run Code Online (Sandbox Code Playgroud)

反正有没有让这个工作的人?不管怎样,我需要一个UDF来调用这个COM对象,或者至少通过这个UDF使用.NET远程访问一些Windows服务.通过这种方式指导我的每一个建议将不胜感激.

谢谢你们.

b0r*_*0rg 5

通常,我不建议使用SQL CLR对象作为COM和SQL之间的桥梁.从安全性开始有很多潜在的警告,并以非常繁琐的发布程序结束,需要物理访问生产sql框,这可能或可能不容易获得.

我还注意到你正在使用Activator.CreateInstance然后提供clsid.在你的原始帖子中,你暗示它是一个COM clsid.我不确定在SQL CLR中创建的AppDomain工作的Activator是否可以实际找到com clsid的对象.

我会尝试的方式:

  • 为您的com创建托管代理
  • 确保它已签名并放入gac
  • 尝试从SQL CLR访问该托管代理

但我真的怀疑它会起作用.任何远程解决方案WCF/WebServices/Remoting甚至SQL Broker似乎都是更好的选择.

简而言之,如果没有看到实际的.net和sql codez,很难再说出更多信息.


Sam*_*les 4

我猜您正在将 CLR 程序集导入到 SQL Server 中?如果是这样,这可能是平台/架构问题。当您构建 DLL 时,您的目标平台是什么?

确保您正在针对正确的平台(即 x86、x64)构建 DLL。

我建议您在 Visual Studio 中的“项目属性”、“构建/平台的目标”中将"Any CPU"项目的平台从 修改为 。"X86"

然后使用"DROP ASSEMBLY",然后使用"CREATE ASSEMBLY",重新导入正确构建的 dll。

您可能还想确保已进行以下更改:

  1. 在 HKey_Classes_Root/Wow6432Node/CLSID 下找到您的 COM 对象 GUID。
  2. 找到后,添加新的 REG_SZ(字符串)值。名称应为 AppID,数据应与您刚刚搜索的 COM 对象 GUID 相同。
  3. 在 HKey_Classes_Root/Wow6432Node/AppID 下添加一个新键。新密钥的名称应与 COM 对象 GUID 的名称相同。
  4. 在刚刚添加的新键下,添加一个新的 REG_SZ(字符串)值,并将其命名为 DllSurrogate。将值留空。
  5. 在 HKey_Local_Machine/Software/Classes/AppID 下创建一个新项(如果尚不存在)。
  6. 同样,新密钥的调用方式应与 COM 对象的 GUID 相同。无需在该键下添加任何值。

另一种解决方案是使用 SQL clr 调用 WCF 服务。请参阅以下我的指南,了解如何执行此操作:

http://www.codeproject.com/Articles/21149/Invoking-a-WCF-Service-from-a-CLR-Trigger