【问题标题】:Entity framework 6 transaction实体框架6事务
【发布时间】:2015-06-25 08:16:14
【问题描述】:

我需要在我的两个表中插入新行,第一个表的自动生成的 id 字段是第二个表的字段之一。目前我正在使用事务来插入数据。我当前的代码如下所示

        using (var context = new ApplicationDatabaseEntities())
        {
            using (var transaction = context.Database.BeginTransaction())
            {
                try
                {
                   foreach (var item in itemList)
                   {
                    context.MyFirstEntity.Add(item);
                    context.SaveChanges();

                    mySecondEntity.MyFirstEntityId = item.Id;
                    context.MySecondEntity.Add(mySecondEntity.MyFirstEntityId );
                    context.SaveChanges();

                   }
                  transaction.Commit();
                }
                catch (Exception ex)
                {
                    transaction.Rollback();
                    Console.WriteLine(ex);

                }
            }
        }

上面的代码工作正常。我的问题是,这是正确的方法吗?我的意思是如果我有 1000 或 2000 个要插入的项目,我当前的代码会影响性能吗

【问题讨论】:

  • 您应该将您的交易包装在using 语句中。
  • 假设您有 1000 个要插入的项目; 999 成功发生,1000 失败......你想回滚所有这些还是只回滚最后一个失败的 1? (你的代码会这样做)。我怀疑它应该离开 999 成功并且只回滚失败的 1 事务。因此,我猜您实际上希望将您的 foreach 放在两个 using 语句之间。

标签: c# entity-framework-6


【解决方案1】:

可以通过隐式事务改进代码:

foreach (var item in itemList)
{
    context.MyFirstEntity.Add(item);
    mySecondEntity.MyFirstEntity = item;
    context.MySecondEntity.Add(mySecondEntity);
}
context.SaveChanges();

注意:我使用了导航属性而不是 id。

【讨论】:

  • 我不需要整个项目只需要一个字段值
  • 您将MyFirstEntityId 分配给item.Id,此代码将在调用SaveChanges() 后执行相同操作。
  • 当您调用 SaveChanges 时,所有内容都包含在一个事务中...使用一个事务来插入 1000 个项目... 999 成功,最后 1 个失败...所以您的 SaveChanges 在循环之外会导致所有 1000 回滚?等等。
  • 此代码将在 SaveChanges 中仅创建一个事务(称为隐式事务)。因此,要么插入所有实体,要么不插入。
  • 实际上,如果所有实体的事务都不重要,则可以在性能方面改进此代码。您可以为每 200 个项目调用 SaveChanges。
【解决方案2】:

这取决于。如果整个批次都必须是事务性的,那么您就没有其他方法可以像在一个大事务中那样做。如果只有元组必须保证事务,那么如果事务时间足够大,您可能会面临一些锁。然后你可以在每个元组的循环中做事务。

您还可以在没有显式事务的情况下一次性完成您正在做的事情。你可以在循环之后SaveChanges,它将是事务性的:

foreach (var item in itemList)
{
    context.MyFirstEntity.Add(item);
    mySecondEntity.MyFirstEntity = item;
    context.MySecondEntity.Add(mySecondEntity);
}
context.SaveChanges();

【讨论】:

    【解决方案3】:

    您应该将事务包装在using 语句中,并在引发异常时回滚。

    using (DbContextTransaction transaction = context.Database.BeginTransaction())
    {
       try
       {
          foreach (var item in itemList)
          {
             context.MyFirstEntity.Add(item);
             mySecondEntity.MyFirstEntity = item;
             context.MySecondEntity.Add(mySecondEntity);
          }
    
          transaction.Commit();
       }
       catch (Exception e)
       {
          transaction.Rollback();
       } 
    }
    

    更多信息here

    【讨论】:

      猜你喜欢
      • 2014-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      • 2017-01-06
      相关资源
      最近更新 更多