2016-09-26 69 views
1

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

我的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,没有任何问题。

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

Begin ReportUpdateTrigger.VTProperty Error sending update to Reporting database: Unable to connect to server 127.0.0.1:27017: The type initializer for 'MongoDB.Bson.Serialization.BsonSerializer' threw an exception.. Done ReportUpdateTrigger.VTProperty

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

我的预感是,无论用户/进程在执行,触发器代码都无法访问Mongo实例。因此“无法连接到服务器127.0.0.1:27017”错误。不知道我的下一步应该是什么。

回答

0

默认情况下,SQLCLR外部访问具有服务帐户的MSSQLSERVER服务(或MSSQL $实例,或类似的东西)的安全上下文(即“登录为”帐户)。该服务帐户默认为本地系统帐户。你可以在这里两件事情之一:

  1. 如果MSSQLSERVER服务使用“本地系统”作为帐户,然后创建一个真正的本地或域/ AD帐户,使该服务帐户。然后确保新的真实账户有权访问MongoDB。

    无论别的什么,通常最好让诸如SQL Server的服务使用自己的服务帐户。这使得更容易控制和限制通过。

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

    对于这一点,你需要添加类似下面给您的代码:

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

我已经改变了SQL Server服务下运行的用户。这是一个本地用户,并且是Administrators组的成员(用于初始测试),但是当我遇到同样的错误时。我使用SSCM更改了用户帐户,并停止/重新启动了服务以确认更改已生效。 如果SQL用户是本地管理员,还有什么可以阻止它访问mongo实例? –

+0

@KyleSullens所以你改变了服务帐户,但仍然不使用模拟,是否正确?如果您还实施了模拟,则服务帐户无关紧要,只需执行SQL Server中执行SQLCLR对象的登录即可。如果不使用模拟,您是否已通过本地用户连接到MongoDB以证明其有效?此外,我只是重新读取错误消息,它来自类型初始值设定项?在这种情况下,您可能无法使用模拟。我不知道类型初始化代码正在做什么。有没有一个会显示连接错误的MongoDB错误日志? –