When your .NET application needs to perform operations across multiple resources (for example, two SQL Server databases, MSMQ, or another transactional resource) and you want them all to succeed or fail together, you can use MSDTC (Microsoft Distributed Transaction Coordinator).
Key idea: MSDTC ensures atomicity across multiple systems. If one operation fails, the transaction coordinator rolls back all other operations automatically.
💡 What is MSDTC?
The Microsoft Distributed Transaction Coordinator (MSDTC) is a Windows service that coordinates transactions that span multiple resource managers, such as:
Multiple SQL Server databases
SQL Server + Message Queue (MSMQ)
SQL Server + Oracle + File System (through transactional NTFS, historically)
🔗 How It Works
When you use TransactionScope in .NET and your code accesses more than one transactional resource, the .NET Framework automatically promotes the transaction to a distributed transaction.
The transaction coordinator (MSDTC) then ensures that:
All resources either commit or roll back.
If any resource fails, MSDTC sends rollback commands to others.
It guarantees two-phase commit (2PC) consistency.
⚙️ Prerequisites
MSDTC service must be running on all participating servers.
Network DTC Access should be enabled (via
dcomcnfgtool).SQL Server must allow distributed transactions.
// To check MSDTC service
services.msc
// or from cmd
net start msdtc
🧩 Example 1: Distributed Transaction with Two SQL Databases
using System;
using System.Data.SqlClient;
using System.Transactions;
class Program
{
static void Main()
{
string connStr1 = "Data Source=SQLSERVER1;Initial Catalog=DbA;Integrated Security=True;";
string connStr2 = "Data Source=SQLSERVER2;Initial Catalog=DbB;Integrated Security=True;";
using (var scope = new TransactionScope())
{
using (var conn1 = new SqlConnection(connStr1))
using (var conn2 = new SqlConnection(connStr2))
{
conn1.Open();
conn2.Open();
var cmd1 = new SqlCommand("INSERT INTO Orders (OrderId, Amount) VALUES (1, 500)", conn1);
var cmd2 = new SqlCommand("INSERT INTO AuditLog (LogId, Description) VALUES (1, 'Order created')", conn2);
cmd1.ExecuteNonQuery();
cmd2.ExecuteNonQuery();
}
// If we reach here, both commands succeeded
scope.Complete();
}
Console.WriteLine("✅ Both databases committed successfully!");
}
}What happens
When you open two SQL connections within the same
TransactionScope, .NET automatically promotes the transaction to MSDTC.MSDTC coordinates the commit between both databases.
If either
cmd1orcmd2fails, the whole transaction rolls back.
Important: If you open only one connection, the transaction remains local and MSDTC is not used.

Join the conversation! Your thoughts help the community grow.