在使用ef&# 39;s DbContext.ExecuteSqlCommand()的事务期间出现异常

本文关键字:事务 异常 ExecuteSqlCommand DbContext ef | 更新日期: 2023-09-27 18:12:28

使用try-catch结构,我试图找出如果在事务的任何一点捕获异常该怎么办。下面是一个代码示例:

try
{
   DbContext.ExecuteSqlCommand("BEGIN TRANSACTION");        //Line 1
   DBContext.ExecuteSqlCommand("Some Insertion/Deletion Goes Here"); //Line 2
   DbContext.ExecuteSqlCommand("COMMIT");                   //Line 3
}
catch(Exception)
{
}   

如果期望在执行'Line 1'时被捕获,除了警告错误之外,什么都不能做。如果它被捕获执行第二行,我不知道我是否需要尝试回滚成功打开的事务,如果第三行出现问题,也会发生同样的情况。

我应该发送回滚吗?或者在一个方法调用中将所有命令直接发送到银行?

在try-catch中有一个循环执行许多事务,就像示例中的事务一样(我需要很多小事务,而不仅仅是一个大事务,所以我可以正确地重用SQL的'_log'文件,并避免它不必要地增长)。

如果任何事务出错,我只需要删除它们并通知发生了什么,但我不能把它变成一个大事务,只是使用回滚,否则它会使日志文件增长到40GB。

在使用ef&# 39;s DbContext.ExecuteSqlCommand()的事务期间出现异常

我想这会有帮助:

using (var ctx = new MyDbContext())
{
    // begin a transaction in EF – note: this returns a DbContextTransaction object
    // and will open the underlying database connection if necessary
    using (var dbCtxTxn = ctx.Database.BeginTransaction())
    {
       try
       {
            // use DbContext as normal - query, update, call SaveChanges() etc. E.g.:
           ctx.Database.ExecuteSqlCommand(
               @"UPDATE MyEntity SET Processed = ‘Done’ "
               + "WHERE LastUpdated < ‘2013-03-05T16:43:00’");
           var myNewEntity = new MyEntity() { Text = @"My New Entity" };
           ctx.MyEntities.Add(myNewEntity);
           ctx.SaveChanges();
           dbCtxTxn.Commit();
       }
       catch (Exception e)
       {
           dbCtxTxn.Rollback();
       }
    } // if DbContextTransaction opened the connection then it will close it here
}

取自:https://entityframework.codeplex.com/wikipage?title=Improved%20Transaction%20Support

基本上,它的想法是你的事务成为using块的一部分,在其中你有一个实际的sql的try/catch。如果在try/catch中有任何失败,它将被回滚

从实体框架6开始,ExecuteSqlCommand被自己的事务包裹,如下所示:http://msdn.microsoft.com/en-gb/data/dn456843.aspx

除非您显式地需要将多个sql命令滚动到单个事务中,否则没有必要显式地开始一个新的事务范围。

关于事务日志的增长,假设您的目标是Sql Server,那么将事务日志操作设置为simple将确保日志在检查点之间被回收。

显然,如果没有在整个导入过程中维护事务日志历史记录,则没有在发生故障时回滚所有数据的隐式机制。为了保持简单,我可能只会添加一个'created' datetime字段到表中,如果我需要在发生错误的情况下删除所有行,则基于对已创建字段的过滤器从表中删除。