避免在System.Transactions中出现事务升级的策略

7
根据我之前的问题的回答,如果在事务期间打开多个连接,即使这些连接具有相同的连接字符串,事务也会从LTM提升到DTC。那么,我的下一个问题是,有什么策略可以避免这种“特性”?基于资源使用,我想尽可能地确保使用LTM。在适当的面向对象业务逻辑层中,我唯一能想到的方法是在数据访问层创建请求级别的静态连接对象,并在调用之间共享,直到请求完成(这里隐含的知识是业务对象实体是离散的,不知道它们将以什么顺序被调用,此外还有一个事实是不希望将连接对象冒泡到业务对象层,因为那将是数据存储实现细节渗透到另一个层)。还有其他人有任何想法,不会完全破坏n层系统的层封装吗?

这是一个非常好的问题,我也在寻找答案。所有的答案总是在简单示例中不够完美,却从未考虑到封装。 - Eduardo Molteni
顺便问一下,既然这个问题已经过时了,你是怎么解决它的?我在考虑使用“环境”连接并进行一些事务计数。我知道这很糟糕。 - Eduardo Molteni
4个回答

2
我使用的是TransactionHelper类,它会更新TableAdapter中的所有命令,将连接和事务替换为发起事务的TableAdapter的连接和事务。你可以在Scott Lanford的博客CodeExperiment上找到执行此操作的一些代码,并根据需要进行调整。Ryan Whitaker也有一个类似的方法
请注意,由于我已经转向使用LINQToSQL,所以不再存在这个问题。您可能要考虑使用LINQToSQL或nHibernate作为替代解决方案。任何一个都可以很好地支持本地事务。

我不使用TableAdapter,而是使用一个SqlDataAdapter,它接受一个命令对象,并完全支持开发人员设置命令对象(因此也包括连接对象)。然而,这并不能解决离散对象调用DAL并需要相同con的问题。 - Robert C. Barth
我也像避开瘟疫一样避免使用LINQ to SQL。有很多我不喜欢的东西,但没有一件是我喜欢的。 - Robert C. Barth

0
我必须问一下,为什么要如此努力地避免使用DTC?在这个问题和之前的回答中都没有提到原因,这让人感觉你可能正在遭受过早优化综合症的困扰。

3
避免使用DTC只是一种好的实践。当你知道你的交易会被升级并且不必如此时,这并不是一种过早的优化。相比轻量级事务协调器,DTC慢得多,因此应该避免使用它。 - Robert C. Barth
DTC并不总是有效。我曾经浪费了一个下午来调试一个服务器,发现它的DTC配置出了神秘的问题,只有后来才发现很多人的服务器都存在DTC服务的问题,可能被禁用或者无法协调事务。 - MatthewMartin
@Robert C. Barth:仅仅为了避免使用DTC而避免使用它并不是好的或推荐的做法,这完全取决于具体情况。你的说法是笼统的,没有提供太多的理由支持。至于如何知道何时会升级事务,那不是TransactionScope的问题,而是编码人员的问题,他们应该在编码时考虑到这一点,因为他们知道它的行为。此外,仅仅因为某些东西更慢,并不意味着应该避免使用它。DTC提供了其他方式无法获得的优势。 - casperOne
1
我并不是为了回避而回避它...我之所以回避它,是因为交易是在单个数据库服务器中进行的,而且没有必要使用 DTC。你提到知道何时会提升事务并让我编写相关代码,这正是我所问的...我该如何编写相关代码?这就是问题的重点。DTC 的功能在单一服务器 MS SQL Server 后端环境中是无用的,这也是本问题的背景。 - Robert C. Barth

0

正如Casper所说,避免DTC可能为时过早,尽管它是一个重要的负担。您可以使用静态工厂实现连接,以便简单地返回新对象,然后如果确定存在问题,可以实现一种机制,可以将事务存储在TLS(或httpcontext,如果您在ASP中)。而不必更改任何代码。

实际上已经提出并回答了这个问题,但我找不到它,当我找到它时,我会更新这个问题。


我在发布问题之前进行了搜索,但是我找不到任何类似的问题。也许我的搜索技巧需要更新一下。;-) - Robert C. Barth
1
使用谷歌搜索时,添加site:stackoverflow.com来限制在该网站内进行搜索。SO的搜索功能相对较差。 - JoshBerke

0
我建议编写一个包装类来管理连接、事务、命令对象,以及所有与数据库相关的事情。这有点像非常轻量级的nHibernate。这个类将提供executeStatement(...)、executeQuery(...)、addParameter(...)、startTransaction(...)等方法。
在开始事务时,您可以提供一些(如果需要唯一的)标识符,以便将所有后续请求与同一事务相关联。然后,这个包装类将保持静态映射,以确定哪个事务正在使用哪个连接,并根据需要自动使用正确的连接或创建新的连接。
通过这种方法,您将获得一些额外的功能,因为您已经集中了所有的持久化内容:
  • 轻松记录所有语句以进行调试和性能测试
  • 在锁定/网络问题上自动重试逻辑
  • 更简单地切换DB提供程序
  • 基本上是一些持久化框架(如nHibernate)所具有的功能,但更轻量级且不那么复杂

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接