简体   繁体   中英

Accessing MongoDB from a SQL Server 2008 CLR trigger

I'm using a SQL CLR trigger to push updates from the relational DB to a MongoDB instance. Both databases are running on the same Windows 2012 machine.

My SQL CLR project is built on .NET 3.5 and is using the mongocsharpdriver 1.10.0.

The C# code within my trigger is as follows:

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");

(this is test code just to verify that the MongoDB operation will work).

I run the exact same code from a separate console app, and the data is posted to Mongo with no problems.

When running from the trigger, I see the following error:

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

I have my DLL (and all supporting DLLs, including the MongoDB drivers) referenced as assemblies within the DB server. CLR is enabled. I know that the trigger is executing because I am getting the custom status and error messages in the SQL output window.

My hunch is that whatever user/process is executing the trigger code does not have access to the Mongo instance. Hence the "Unable to connect to server 127.0.0.1:27017" error. Not sure what my next step should be.

By default, SQLCLR external access has a security context of the service account (ie "Logon As" account) of the MSSQLSERVER service (or MSSQL$InstanceName , or something like that). And that service account, by default, is the Local System account. You can do one of two things here:

  1. If your MSSQLSERVER service is using "Local System" as the account, then create a real local or domain / AD account and make that the service account. Then just make sure that the new real account has access to MongoDB.

    Regardless of anything else, it is often best to have services such as SQL Server uses their own service accounts. That makes it easier to control and confine the permssions.

  2. If you are using Windows logins, then you have the option of enabling Impersonation in the .NET code. When using Impersonation, the security context of external calls is set to the Windows Login that is executing the SQLCLR object.

    For this, you would need to add something like the following to your code:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM