我有一个helluva时间将几个事务包装到同一个SQL Server上的两个不同的数据库中。我最初遇到网络DTC访问问题,我解决了这个问题。现在,我继续得到的错误是“与底层事务管理器的通信失败了。”
我们在数据库中有一些客户配置文件,当这些配置文件过时时,我们希望将它们移动到“存档”数据库进行存储。此举简单(幽默斜体)将它们添加到存档数据库并从主/实时数据库中删除它们。我为每个数据库都有一个DataContext。下面的代码执行Add,然后在尝试使用第二个DataContext时获取Delete上的错误。我只和LINQ合作了几个月,过去几天我一直在搜索文章。我想知道我的代码是否有任何问题,或者是否仍然没有正确配置DTC或???
我们在VMware上运行我的工作站和服务器。 - Workstation是Windows 7 SP1 - 服务器是Windows和SQL Server 2008R2
'移动'的常规:
private int MoveProfileToArchiveDB( int iProfileId )
{
int rc = RC.UnknownError;
// get new Archive profile object
ProfileArchive.ProfileInfo piArchive = new ProfileArchive.ProfileInfo();
// 'Live' DataContext
using ( ProfileDataContext dbLive = new ProfileDataContext() )
{
// get Live profile
ProfileInfo piLive = ProfileInfo.GetProfile( dbLive, iProfileId );
// copy Live data to Archive profile object... including the id
ProfileArchive.ProfileInfo.CopyFromLive( piLive, piArchive, true );
}
bool bArchiveProfileExists = ProfileArchive.ProfileInfo.ProfileExists( piArchive.id );
// make the move a transaction...
using ( TransactionScope ts = new TransactionScope() )
{
// Add/Update to Archive db
using ( ProfileArchiveDataContext dbArchive = new ProfileArchiveDataContext() )
{
// if this profile already exists in the Archive db...
if ( bArchiveProfileExists )
{
// update the personal profile in Archive db
rc = ProfileArchive.ProfileInfo.UpdateProfile( dbArchive, piArchive );
}
else
{
// add this personal profile to the archive db
int iArchiveId = 0;
piArchive.ArchiveDate = DateTime.Now;
rc = ProfileArchive.ProfileInfo.AddProfile( dbArchive, piArchive, ref iArchiveId );
}
// if Add/Update was successful...
if ( rc == RC.Success )
{
// Delete from the Live db
using ( ProfileDataContext dbLive = new ProfileDataContext() )
{
// delete the personal profile from the Profile DB
rc = ProfileInfo.DeleteProfileExecCmd( dbLive, iProfileId ); // *** ERROR HERE ***
if ( rc == RC.Success )
{
// Transaction End (completed)
ts.Complete();
}
}
}
}
}
return rc;
}
注意:
非常感谢任何帮助!非常感谢...
答案 0 :(得分:8)
而不是继续交叉评论,我决定将其作为答案发布。
不要使用错误代码。这就是例外情况。代码流更难以阅读,错误代码返回邀请被忽略。例外使代码更容易阅读,更不容易出错。
如果您使用TransactionScope,请记住始终明确设置隔离级别。见using new TransactionScope() Considered Harmful。 SERIALIZABLE的隐含隔离级别几乎从未被要求,并且具有巨大的负面影响。
交易升级。每当在事务范围内打开多个连接时,它们就可以将事务升级为分布式事务。行为因版本而异,有些人试图将其记录下来,例如。 TransactionScope: transaction escalation behavior:
SQL Server 2008比SQL Server 2005更加智能,而且可以 如果所有数据库连接都是自动检测的 事务指向同一个物理数据库。如果是这种情况, 该事务仍然是本地事务,并且不会升级到 分布式交易。不幸的是,有一些警告:
- 如果嵌套了打开的数据库连接,则事务仍然存在 升级到分布式事务。
- 如果在交易中,a 连接是另一个持久资源,事务是 立即升级为分布式交易。
由于您的连接(来自使用的两个数据上下文)指向不同的数据库,即使在SQL Server 2008上,您的TransactionScope也会升级到分布式事务。
将您的申请纳入DTC至少有两种方式:
现在,如果你按照上面提到的文章修复MSDTC通信,你的代码应该正常工作,但我仍然相信这个归档应该不在运行EF的客户端代码中出现。有更好的工具,SSIS是一个很好的例子。运行SSIS的夜间计划作业将更有效地传输这些未使用的配置文件。