我正在花费大量时间将几个事务包装到同一 SQL Server 上的 2 个不同数据库。我最初在网络 DTC 访问方面遇到问题,我解决了这个问题。现在,我继续收到的错误是“与底层事务管理器的通信失败”。
我们的数据库中有一些客户资料,当这些资料过时时,我们希望将它们移至“存档”数据库进行存储。此举很简单(斜体为幽默)将它们添加到存档数据库并从主/实时数据库中删除它们。我为每个数据库都有一个 DataContext。下面的代码执行添加操作,然后在尝试使用第二个 DataContext 时在删除操作上出现错误。我使用 LINQ 才几个月,过去几天我一直在浏览文章。我想知道我的代码是否有问题,或者是否仍有某些内容未正确配置 DTC 或 ???
我们的工作站和服务器在 VMware 上运行。
- 工作站是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;
}
NOTES:
- 我有几种不同的删除方法,它们都在 TransactionScope 之外工作。
- ProfileInfo 是主要的配置文件表,对于实时数据库和存档数据库大致相同。
任何帮助是极大的赞赏!非常感谢...
我决定将其作为答案发布,而不是继续纵横交错的评论。
-
不要使用错误代码。这就是例外的用途。代码流更难以阅读,并且错误代码返回邀请被忽略。异常使代码更易于阅读并且更不易出错。
-
如果您使用 TransactionScope,请记住始终显式设置隔离级别。看使用 new TransactionScope() 被认为是有害的 https://learn.microsoft.com/en-us/archive/blogs/dbrowne/using-new-transactionscope-considered-harmful。 SERIALIZABLE 的隐式隔离级别几乎从不被需要,并且会产生巨大的负面规模影响。
-
交易升级。每当在事务范围内打开多个连接时,它们就可以将事务升级为分布式事务。行为因版本而异,有些人试图记录它,例如。TransactionScope:事务升级行为 http://pieterderycke.wordpress.com/2012/01/22/transactionscope-transaction-escalation-behavior/:
SQL Server 2008 比 SQL Server 2005 更加智能,并且可以
自动检测是否所有数据库连接都在某个
事务指向同一个物理数据库。如果是这样的话,
该事务仍然是本地事务并且不会升级为
分布式事务。不幸的是,有一些警告:
- 如果打开的数据库连接是嵌套的,事务仍然是
升级为分布式事务。
- 如果在交易中,
连接到另一个持久资源,事务是
立即升级为分布式事务。
由于您的连接(来自所使用的两个数据上下文)指向不同的数据库,因此即使在 SQL Server 2008 上,您的 TransactionScope 也会升级为分布式事务。
将您的应用程序纳入 DTC 至少在两个方面是有害的:
- 吞吐量将通过地板下沉。数据库每秒可以支持几千个本地事务,但每秒只能支持数十个(可能是数百个)分布式事务。这主要是因为其复杂性两阶段提交 http://en.wikipedia.org/wiki/Two-phase_commit_protocol.
- DTC 需要一个协调员:MSDTC。 [MSDTC 的安全增强功能] 使配置更具挑战性,开发人员发现他们的应用程序需要 MSDTC 肯定是出乎意料的。链接的文章中描述的步骤可能是您现在缺少的。对于 Windows Vista/Windows 7/Windows Server 2008/Windows Server 2008R2,步骤如下所述Windows Vista 和 Windows Server 2008 中的 MSDTC http://blogs.msdn.com/b/chrisforster/archive/2008/02/19/msdtc-in-windows-vista-and-windows-server-2008.aspx, in 如何在 Windows 2008 上配置 DTC http://itknowledgeexchange.techtarget.com/sql-server/how-to-configure-dtc-on-windows-2008/以及其他类似的文章。
现在,如果您按照上述文章修复 MSDTC 通信,您的代码应该可以工作,但我仍然相信此归档应该not发生在运行 EF 的客户端代码中。有更好的工具,SSIS http://msdn.microsoft.com/en-us/library/ms141026.aspx就是一个很好的例子。每晚运行 SSIS 的计划作业将更有效地传输那些未使用的配置文件。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)