使用EF的DbContext.ExecuteSqlCommand()进行事务期间的异常

时间:2014-07-11 19:17:22

标签: c# sql-server entity-framework-6

使用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)
{
}   

如果在执行'第1行'时捕获了预测,除了警告错误之外,不必做任何事情。如果它被捕获执行第二行我不知道我是否需要尝试回滚已成功打开的事务,并且如果第三行出错则会发生同样的情况。

我是否应该发送回滚?或者通过单个方法调用将所有命令直接发送到银行?

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

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

2 个答案:

答案 0 :(得分:6)

认为这会有所帮助:

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块的一部分,并且在其中你有一个try / catch与实际的sql。如果try / catch中有任何失败,它将被回滚

答案 1 :(得分:2)

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

除非您明确需要将多个sql命令滚动到单个事务中,否则无需显式开始新的事务范围。

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

显然,如果没有在整个导入中维护事务日志历史记录,则在发生故障时没有隐式机制来回滚所有数据。保持简单,我可能只是在表中添加一个“创建的”日期时间字段,并根据对创建字段的过滤器从表中删除,如果我需要在发生错误时删除所有行。