【发布时间】:2014-10-10 21:06:04
【问题描述】:
我有一个带有多个数据库的服务器,每个数据库将使用不同的用户 ID pswd 连接。 我需要更新/插入/删除任何数据库中表中的记录。如果发生任何错误 - 将所有更改回滚到当前事务中的所有数据库。
我的代码如下:
string connStrTest1 = "connectionstring to connect to DB1";
string connStrTest2 = "connectionstring to connect to DB2";
string connStrTest3 = "connectionstring to connect to DB3";
//For an example I have created 3 DBs which have the same tables and columns.
string InsertPerson = "insert into Person (Id, Name, City) VALUES (123, 'Jon' , 'England' )";
string InsertPhones = "insert into Phones (Id, Number, SrvcPrvdr) VALUES (123, '+442345678' , 'Some')";
string InsertWork = "INSERT INTO WorkPlace (Id, Office, Address) VALUES (123, 'Soem', 'England' )";
string FailInsertWork = "INSERT INTO WorkPlace (Id, Office, Address) VALUES (999, 'some', 'Australia' )";
static void Main()
{
using (var connTest1 = new SqlConnection(connStrTest1))
{
connTest1.Open();
var transaction = connTest1.BeginTransaction();
try
{
//Update 1st DB here.....
var command = new SqlCommand(InsertPerson, connTest1, transaction);
command.CommandType = System.Data.CommandType.Text;
command.CommandText = InsertPerson;
command.ExecuteNonQuery();
command.CommandText = InsertPhones;
command.ExecuteNonQuery();
command.CommandText = InsertWork;
command.ExecuteNonQuery();
//updating DBs 2 & 3 here
updateRecords();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
throw ex;
}
}
}
private static void updateRecords()
{
//Updating tables in 2nd Test DB
using (var conn = new SqlConnection(connStrTest2))
{
conn.Open();
try
{
var command = new SqlCommand(InsertPerson, conn);
command.CommandType = System.Data.CommandType.Text;
command.ExecuteNonQuery();
command.CommandText = InsertPhones;
command.ExecuteNonQuery();
command.CommandText = InsertWork;
command.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
}
//Updating tables in 3rd Test DB
using (var conn = new SqlConnection(connStrTest3))
{
conn.Open();
try
{
var command = new SqlCommand(InsertPerson, conn);
command.CommandType = System.Data.CommandType.Text;
command.ExecuteNonQuery();
command.CommandText = InsertPhones;
command.ExecuteNonQuery();
if (fail)
{
command.CommandText = FailInsertWork;
command.ExecuteNonQuery();
}
else
{
command.CommandText = InsertWork;
command.ExecuteNonQuery();
}
}
catch (Exception ex)
{
throw ex;
}
}
}
在查询 FailInsertWork 中,我编写了查询,以便在发生外键冲突时引发异常。
现在,我希望我的程序能够在更新到第三个数据库失败时运行,之前为第一和第二个数据库发生的所有插入也应该回滚。
您可以将 connectionString 或连接实例或事务实例传递给 updateRecords 方法。
仅供参考 - 我不想使用 TransactionScope/DTC/System.Transactions.Transaction。
高度赞赏除此之外的任何其他解决方案。
【问题讨论】:
-
为什么不想使用 DTC?它专为您的用例而设计。我很好奇你为什么要重新发明轮子。
-
这正是实现分布式事务/XA 事务的目的。实施您自己的 2PC 系统很容易出错,并且可能永远无法在所有恢复方案中正常工作。
标签: c# sql transactions