我们正在从源数据库到目标数据库执行导入过程。我们需要经常以自动方式运行这些导入。
源位于与目标不同的服务器上。两者都是MS SQL 2008.我们使用Linq2SQL访问源,使用自定义数据层访问目标。我们不会修改源数据库(虽然我们目前不会将其恢复为只读)。但是,现在当我们在transactionScope中运行导入时,整个事务将被提升为DTC,因为我们在不同的服务器上访问两个DB。
如果我们要将源数据库设为只读,它还会这样做吗?
有关如何在此方案中避免DTC促销的任何其他建议?
Remus回答的后续问题(再次感谢):
后续行动#1: 我的导入例程的结构使得它从源中导入记录并在目标中创建新记录。像这样:
using(var scope = new TransactionScope())
{
// read some from source db using Linq2Sql
// transform source info
// update destination
// read some more from source db using Linq2Sql
// transform source info
// update destination
}
您是否想要使用RequiresNew在TransactionScope中包围Linq2Sql位?或者,我猜,我真的不关心源头上的交易,我可以用TransactionScope包围这个连接包含在任何交易中,对吧?
后续行动#2:
当你说“打开第二个连接,甚至连同一个数据库”时 - 我已经阅读了几个变种:
答案 0 :(得分:2)
当您在事务范围内打开第二个ADO.Net连接时,两个连接都将被提升为DTC。即使是与同一个DB的新连接,也无所谓。数据库只读也与它无关,也不可能与它有任何关系。首先,连接不是特定于数据库的,因为它们可以在打开后更改数据库。其次,只读数据库可以执行大量写操作(例如,可以调用readonlydb.dbo.myProcedure,在程序中我可以更新writabledb.dbo.table)。
如果要避免使用DTC,则必须在两个访问层之间使用不同的事务范围(即使用RequireNew创建新范围)。
<强>更新强>
如果可以在范围之外进行读取,那将是完美的:
// read some from source db using Linq2Sql
// read some more from source db using Linq2Sql
using(var scope = new TransactionScope())
{
// transform source info
// update destination
// transform source info
// update destination
}
我理解这是非常不可能的,因为第二组读取可能通常依赖于第一次转换/更新的结果。因此,在阅读时最好压缩范围:
using(var scope = new TransactionScope())
{
using(var nada= new TransactionScope(TransactionScopeOption.Supress))
{
// read some from source db using Linq2Sql
// transform source info
}
// update destination
using(var nada= new TransactionScope(TransactionScopeOption.Supress))
{
// read some more from source db using Linq2Sql
// transform source info
}
// update destination
}
BTW我认为'使用linq读取一些数据'意味着你实际上枚举了查询,不要只创建查询表达式并稍后使用表达式。我不确切知道事务范围如何与查询表达式交互,但我的假设是范围适用于查询执行,而不是声明。