如何使用存储过程在 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 中使用事务?的主要内容,如果未能解决你的问题,请参考以下文章

LINQ to SQL语句(20)之存储过程

Linq to SQL - 视图与存储过程

Linq to sql-存储过程

通过 LINQ-to-SQl 加载数据集

带有存储过程的实体框架 VS LINQ to SQL VS ADO.NET? [关闭]

Linq to Sql vs Nhibernate vs SubSonic vs 存储过程(帮助)