【问题标题】:Transactions commit and rollback with Entity Framework, Mysql and LINQ to SQL in C#在 C# 中使用 Entity Framework、Mysql 和 LINQ to SQL 提交和回滚事务
【发布时间】:2026-01-28 14:15:02
【问题描述】:

我的问题是transaction 工作不正常,如果在trascation 期间发生异常,它不应该为一个表保存数据

当所有表格都正确时,只保存数据。

考虑以下几点:

databaseEntites objEntites = null;  
using (objEntites = new databaseEntites())  
{
     objEntites.Connection.Open();  
     using (System.Data.Common.DbTransaction transaction = 
         objEntites.Connection.BeginTransaction())
     {
         try
         {  
             customer objcust=new customer();  
             objcust.id=id;  
             objcust.name="test1";  
             objcust.email="test@gmail.com";  
             objEntites.customer.AddObject(objcust);  

             order objorder=new order();  
             objorder.custid=objcust.id;  
             objorder.amount=500;  
             objEntites.order.AddObject(objorder);  

             objEntites.SaveChanges();  
             transaction.Commit();  
         }  
         catch()  
         {  
             transaction.Rollback();  
         }  
     }  
}

在这个我的第二个表列名不正确,SaveChanges() 给出了例外。

当我看到数据库并发现它为客户表保存了错误的数据时,我希望当所有表都正确时数据将进入客户表,并且此 savechanges 要么保存所有表,要么不保存任何表。

为此,我也尝试了TransactionScope

using (TransactionScope tscope = 
    new TransactionScope(TransactionScopeOption.RequiresNew))
{
......all the code here....
    objEntites.SaveChanges(false);

    tscope.Complete();
    objEntites.AcceptAllChanges();
}

但它给出了与上述相同的问题。

提前致谢。

【问题讨论】:

  • SaveChanges() 无法部分保存数据。它始终是一笔交易,您无需自己管理交易。如果您注意到部分数据已保存,则您的代码中一定存在其他问题。
  • 我有一个关于你的问题的最新消息 - 如果有帮助,请告诉我。

标签: c# mysql entity-framework linq-to-sql transactions


【解决方案1】:

您可以使用数据库事务或 EF TransactionScope。对于使用数据库事务,如下操作就足够了:

using (var dbContextTransaction = context.Database.BeginTransaction()) 
{
  try
  {
    //Some stuff
    dbContextTransaction.Commit(); 
  } 
  catch (Exception) 
  { 
    dbContextTransaction.Rollback(); 
  }
} 

对于使用 EF TransactionScope 的第二种方式,如下所示:

using (var scope = new TransactionScope(TransactionScopeOption.Required)) 
    {  
      try
      {
        //Some stuff
        scope.Complete(); 
      } 
      catch (Exception) 
      { 
         //Don't need call any rollback like method
      }
    } 

关键是 TransactionScope 中不存在 Rollback() 方法(与正常的 ADO.NET 事务相反),除非您调用 Complete() 方法,否则事务不会完成并且所有更改都会自动回滚。你可以看MSDN更好的理解:http://msdn.microsoft.com/en-us/data/dn456843.aspx

希望有帮助

【讨论】:

    【解决方案2】:

    如果您已经有try ... catch 块,则不需要using - 只需添加finally。下面的例子应该有你需要的一切:

    databaseEntites objEntites = null;
    var System.Data.Common.DbTransaction transaction = null;
    try
    {  
        objEntites = new databaseEntites();
        objEntites.Connection.Open();  
        transaction = objEntites.Connection.BeginTransaction();
        customer objcust=new customer();  
        objcust.id=id;  
        objcust.name="test1";  
        objcust.email="test@gmail.com";  
        objEntites.customer.AddObject(objcust);  
    
        order objorder=new order();  
        objorder.custid=objcust.id;  
        objorder.amount=500;  
        objEntites.order.AddObject(objorder);  
    
        objEntites.SaveChanges();  
        transaction.Commit();  
    }  
    catch()  
    {  
        if (transaction != null) transaction.Rollback();
    }  
    finally
    {
        if (objEntites != null && objEntites.Connection.State != System.Data.ConnectionState.Closed 
            && objEntites.Connection.State != System.Data.ConnectionState.Broken) 
            objEntites.Connection.Close();
    }
    

    提示:

    • finally 块即使在发生异常后也会执行,因此如果发生异常,首先执行异常处理代码,然后是 finally 块中的代码。仅当发生严重异常(系统错误)(例如 *Exception)时,才不会执行它,但无论如何您都无法轻松处理此类异常。有关此主题的更多信息,请查看here.

    • 对于SaveChanges,您还可以使用选项System.Data.Objects.SaveOptions.AcceptAllChangesAfterSave,因为它保证每个实体对象在成功保存后都会接受其更改。

    • BeginTransaction 还允许指定事务类型,但我不会使用参数选项,因为如果您省略它,那么它会创建数据库默认指定的事务 - 所以管理员仍然能够如果需要,可以轻松更改。但如果需要指定,请确保不要硬编码,而是允许在 App.Config 或 Web.Config 文件中进行配置。

    如果这对你有用,请告诉我。

    【讨论】:

    • 通过选择 innodb mysql 类型,我的代码只对数据库进行了一次更改。
    • 对不起,我没明白你的意思。请详细说明。
    • 我很好奇您是否忽略了使用并手动捕获事务中的异常并回滚任何异常?为什么???
    • 我刚刚从问题中选择了 catch 块。当然,您可以进行细粒度检查以查看事务是否需要回滚。我同意这样做总是更好,应该尽可能地这样做。
    最近更新 更多