如何使用存储过程在 LINQ to SQL 中使用事务?
Posted
技术标签:
【中文标题】如何使用存储过程在 LINQ to SQL 中使用事务?【英文标题】:How do I use a transaction in LINQ to SQL using stored procedures? 【发布时间】:2010-10-30 17:10:12 【问题描述】:我有一段看起来像这样的代码(ClearImportTable 和 InsertPage 是存储过程):
datacontext.ClearImportTable() //Essentially a DELETE FROM table
for (int i = 1; i < MAX_PAGES; ++i)
datacontext.InsertPage(i); //Inserts data into the table
这是我的代码的一个稍微简化的版本,但它的想法是在插入记录之前清除表。唯一的问题是,如果在 ClearImportTable 之后发生错误,表中的所有数据都会被擦除。有没有办法将它包装在事务中,以便如果有任何错误,一切都会恢复原状?
【问题讨论】:
【参考方案1】:你可以做一个事务范围:
using (var transaction = new TransactionScope())
// do stuff here...
transaction.Complete();
如果发生异常或使用块未命中 transaction.Complete(),则在使用块中执行的所有操作都会回滚。
您需要引用 System.Transactions 程序集。
【讨论】:
我相信只有在事务中创建多个 linq 数据上下文并对它们运行查询时才需要 MSDTC。如果您只在事务范围内创建一个数据上下文对象,则不需要。 MSDTC 仅在涉及多个资源管理器时才需要。只要您只涉及单个 DataContext 并连接到单个 SQL Server 实例,那么您应该使用轻量级事务。 其实需要一个分布式事务。我忘了,其中一个存储过程使用 OPENQUERY。我收到此错误消息: System.Data.SqlClient.SqlException:无法执行操作,因为链接服务器“HOUSING_ODSPROD”的 OLE DB 提供程序“OraOLEDB.Oracle”无法开始分布式事务。链接服务器“HOUSING_ODSPROD”的 OLE DB 提供程序“OraOLEDB.Oracle”返回消息“新事务无法加入指定的事务协调器。”这是否意味着我搞砸了?【参考方案2】:正如上面提到的“航海柔道”,当我需要调用存储过程时,我已经成功地使用了 TransactionScope 块。但是,我遇到了一个“陷阱”,其中一个异常被抛出,说“事务有问题”。为了解决这个问题,我必须在 proc 上调用一个非延迟方法以使其立即评估结果。所以不是
using (var transaction = new TransactionScope())
var db = new dbDataContext();
db.StoredProc();
transaction.Complete();
我不得不这样称呼它......
using (var transaction = new TransactionScope())
var db = new dbDataContext();
db.StoredProc().ToList();
transaction.Complete();
在此示例中,ToList() 可以是任何非延迟方法,它会导致 LINQ 立即评估结果。
我认为这是因为 LINQ 的惰性(延迟)性质不能很好地适应事务的时间安排,但这只是一个猜测。如果有人能对此有所了解,我很想听听。
【讨论】:
【参考方案3】:在 DataContext 上设置 Transaction 属性?
【讨论】:
以上是关于如何使用存储过程在 LINQ to SQL 中使用事务?的主要内容,如果未能解决你的问题,请参考以下文章