3

我的问题是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();
}

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

提前致谢。

4

2 回答 2

3

您可以使用数据库事务或 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

希望这有帮助

于 2014-12-17T08:58:20.793 回答
0

如果您已经有一个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块中的代码。仅当发生严重异常(系统错误)(例如 StackOverflowException)时,才不会执行它,但无论如何您都无法轻松处理此类异常。有关此主题的更多信息,请查看此处。

  • 因为SaveChanges您也可以使用 option System.Data.Objects.SaveOptions.AcceptAllChangesAfterSave,我更喜欢它,因为它保证每个实体对象在成功保存后都接受其更改。

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

请让我知道这是否适合您。

于 2013-07-23T08:40:05.923 回答