通过SQL Server 2008 CLR触发器访问MongoDB



我使用SQL CLR触发器将更新从关系数据库推送到MongoDB实例。这两个数据库都运行在同一台Windows 2012机器上。

我的SQL CLR项目是在。net 3.5上构建的,使用的是mongocsharpdriver 1.10.0。

我的触发器中的c#代码如下:
SqlPipe pipe = SqlContext.Pipe;
pipe.Send("Begin ReportUpdateTrigger.VTProperty");
try
{
    var settings = new MongoClientSettings();
    settings.Server = new MongoServerAddress("127.0.0.1", 27017);
    var client = new MongoClient(settings);
    var server = client.GetServer();
    var db = server.GetDatabase("VTProperty");
    var coll = db.GetCollection<object>("Property");
    var item = new { name = "test", datecreated = DateTime.Now };
    coll.Insert(item);
}
catch (Exception ex)
{
    pipe.Send("Error sending update to Reporting database: " + ex.Message);
}
pipe.Send("Done ReportUpdateTrigger.VTProperty");

(这是测试代码,只是为了验证MongoDB操作是否正常工作)。

我从一个单独的控制台应用程序运行完全相同的代码,数据被发布到Mongo没有问题。

当从触发器运行时,我看到以下错误:

ReportUpdateTrigger开始。VTProperty向Reporting发送更新错误数据库:无法连接到服务器127.0.0.1:27017:类型MongoDB.Bson.Serialization的初始化器。BsonSerializer抛出了异常. .ReportUpdateTrigger完成。VTProperty

我有我的DLL(和所有支持DLL,包括MongoDB驱动程序)引用为DB服务器内的程序集。CLR已启用。我知道触发器正在执行,因为我在SQL输出窗口中获得自定义状态和错误消息。

我的预感是,无论用户/进程正在执行触发器代码没有访问Mongo实例。因此出现"无法连接到服务器127.0.0.1:27017"错误。不知道下一步该怎么做

默认情况下,SQLCLR外部访问具有服务帐户的安全上下文(即。MSSQLSERVER服务的"登录为"帐户)(或MSSQL$InstanceName,或类似的东西)。默认情况下,该服务帐户是本地系统帐户。您可以在这里执行以下两种操作之一:

  1. 如果您的MSSQLSERVER服务使用"本地系统"作为帐户,那么创建一个真正的本地或域/AD帐户,并使其成为服务帐户。然后确保新的真实帐户可以访问MongoDB。

    无论其他什么,通常最好让服务(如SQL Server)使用自己的服务帐户。

  2. 如果您正在使用Windows登录,那么您可以选择在。net代码中启用模拟。当使用Impersonation时,外部调用的安全上下文被设置为正在执行SQLCLR对象的Windows Login。

    为此,您需要在代码中添加如下内容:
    using System.Security.Principal;
    // above the "try" block
    WindowsImpersonationContext _ImpersonationIdentity = null;
    // inside the "try", before anything else
    _ImpersonationIdentity = SqlContext.WindowsIdentity.Impersonate();
    // in a "finally" block
    if (_ImpersonationIdentity != null)
    {
      _ImpersonationIdentity.Undo();
    }
    

最新更新