We are using Entity Framework 6 and are dealing with the following requirement:
We are writing data to two different and independent databases let's call them Main and External, they both exist on the same instance of SQL Server and the connection string used to connect to them are identical except for the initial catalog value.
In the application each DB has its own EF DBContext.
The Main DB has an AuditLog table in which data changes get recorded.
Data changes that happen on the External DB need to be recorded on the AuditLog table within Main DB.
Because of certain restrictions that are not important to discuss the way we implemented this was to have ExternalContext to have a reference of MainContext in order to call MainContext.SaveAuditLogs whenever ExternalContext.SubmitChanges was called, like so (only showing relevant code):
public class ExternalContext : IDataContext
{
private readonly IAuditLogContext auditLogContext;
public ExternalContext (IAuditLogContext auditLogContext){
this.auditLogContext = auditLogContext;
}
public override void SaveChanges()
{
base.SaveChanges();
this.auditLogContext.SaveAuditLogs(auditLogs);
}
}
public class MainContext : IAuditLogContext
{
public void SaveAuditLogs(List<AuditLog> auditLogs)
{
this.Set<AuditLog>().AddRange(auditLogs);
this.SaveChanges();
}
}
An example of how this is being used:
public class SomeBusinessClass
{
private readonly IDataContext dataContext;
public SomeBusinessClass(IDataContext dataContext)
{
this.dataContext = dataContext;
}
public void SomeOperation(Entity someEntity)
{
.....
using(var scope = new TransactionScope())
{
this.dataContext.Insert(someEntity);
this.dataContext.SaveChanges();
}
scope.Complete();
}
}
For this to work the Distributed Transaction Coordinator service needs to be running. When tested on development environments it works fine but on QA environments it fails with the error message as if the Distributed Transaction Coordinator is not running even though it is.
Apparently this happens because in our development environments the DB Server and the Web Server are the same computer weather in QA they are two separate boxes and the DTC does not like it when there are multiple servers and the two operations run within a TransactionScope, if we remove the TransactionScope then it works fine on both environments but then there is the risk that if the AuditLog fails the whole transaction is not rolled back.
How can we make this work?
Thank you.