【问题标题】:How to Remove Range after Add Range in same operation如何在同一操作中添加范围后删除范围
【发布时间】:2020-05-15 05:30:59
【问题描述】:

我需要RemoveRange(总记录),然后将新数据添加到表中。在此我收到以下错误:

在前一个操作完成之前,在此上下文中启动了第二个操作。这通常是由使用相同 DbContext 实例的不同线程引起的,但不能保证实例成员是线程安全的。这也可能是由于在客户端上评估嵌套查询造成的,如果是这种情况,请重写查询以避免嵌套调用。

下面是我的代码

using (var transaction = context.Database.BeginTransaction())
{
    List<Permission> permission = context.permissions.ToList();
    context.permissions.RemoveRange(permission);
    context.SaveChangesAsync();
    var permissions = new Permission[]
    {
        new Permission { PermissionId=1, Resource = "User Info", CanMenuItem = true ,Action= "Get", AppICON="User.jpg", WebICON="ft-users", APPURI="UserPage", WebURI="", IsActive=true,  Notify=false, UpdatedOn = System.DateTime.Now, SortBy = 1 },
        new Permission { PermissionId=2, Resource = "User", CanMenuItem = false ,Action= "Get", AppICON="User.jpg", WebICON="", APPURI="UserPage", WebURI="/user", IsActive=true, Parent=1, Notify=false, UpdatedOn = System.DateTime.Now, SortBy = 1 },
        new Permission { PermissionId=3, Resource = "User", Action= "Post", AppICON="", WebICON="", APPURI="", WebURI="", IsActive=true, Notify=false, UpdatedOn = System.DateTime.Now },
        new Permission { PermissionId=4, Resource = "User", Action= "Put", AppICON="", WebICON="", APPURI="", WebURI="", IsActive=true, Notify=false, UpdatedOn = System.DateTime.Now },
        new Permission { PermissionId=5, Resource = "User", Action= "Delete", AppICON="", WebICON="", APPURI="", WebURI="", IsActive=true, Notify=false, UpdatedOn = System.DateTime.Now },
    }

    context.permissions.AddRange(permissions);
    context.Database.ExecuteSqlCommand(@"SET IDENTITY_INSERT [dbo].[Permission] ON");
    context.SaveChanges();
    context.Database.ExecuteSqlCommand(@"SET IDENTITY_INSERT [dbo].[Permission] OFF");
}

我想从表中删除所有数据并在同一次调用中向表中添加新数据?

【问题讨论】:

  • 请对SaveChangesAsync() 方法使用异步等待或将其重命名为SaveChanges()。我认为这会导致您出现异常。
  • @Richard Baldauf ...是的,这就是原因......现在使用 savechanges() 可以正常工作
  • Nooo... 你有一个有效的 async/await 树设置,为什么要同步执行这样一个可能很长的操作?现在您可能会收到警告“不包含等待并且将...”,因为您的方法仍被标记为异步,但您没有执行任何异步操作
  • Btw ExecuteSqlCommand 已过时。必须使用 ExecuteSqlRaw。
  • 第一个SaveChangesAsync 调用开始在与主线程不同的线程中运行操作。如果在调用SaveChanges 时它没有完成,你会得到这个错误。为避免这种情况,您必须等待第一个操作完成。正如所指出的,您在这里有几个选择。如果您想保留async 电话,您可以await 它。或者将 SaveChangesAsync 更改为 SaveChanges 也可以,因为下一条语句在完成之前不会执行。

标签: c# sql-server entity-framework linq asp.net-core


【解决方案1】:

正如 Richárd 在 cmets 中指出的那样,通过在顶部使用 SaveChangesAsync 而无需任何技术来等待它完成,您最终会尝试同时运行两个操作,因为之后的代码肯定会花费更少运行时间比“全部下载然后删除”。

将其交换为 SaveChanges(最不推荐),或等待它,以便您的代码停止并等待删除完成,然后再执行添加(更好),或将其完全删除并只保存一次异步(可能最好)

//this
context.permissions.RemoveRange(permission)(
var permissions = new Permission[]

//or this
context.permissions.RemoveRange(permission);
await context.SaveChangesAsync();
var permissions = new Permission[]

//or this
context.permissions.RemoveRange(permission);
context.SaveChanges();
var permissions = new Permission[]

我个人会使用第一个并在最终保存时使用 async/await,因为这可能是一个很长的操作,而且您似乎已经设置了异步层次结构

此外,如果此表中有很多行,您可能不想全部下载它们,只是像在此处那样删除它们。阅读Entity Framework. Delete all rows in table - 有办法让数据库直接转储所有行

【讨论】:

    【解决方案2】:

    在玩的过程中,我意识到代码也缺少提交。所以我决定发布一个完整的代码。

    using (var transaction = context.Database.BeginTransaction())
    {
        List<Permission> permission = context.Permission.ToList();
        context.Permission.RemoveRange(permission);
        //context.SaveChanges();  // Not needed
    
        var permissions = new Permission[]
        {
            new Permission { PermissionId=1, Resource = "User Info", CanMenuItem = true ,Action= "Get", AppICON="User.jpg", WebICON="ft-users", APPURI="UserPage", WebURI="", IsActive=true,  Notify=false, UpdatedOn = System.DateTime.Now, SortBy = 1 },
            new Permission { PermissionId=2, Resource = "User", CanMenuItem = false ,Action= "Get", AppICON="User.jpg", WebICON="", APPURI="UserPage", WebURI="/user", IsActive=true, Notify=false, UpdatedOn = System.DateTime.Now, SortBy = 1 },
            new Permission { PermissionId=3, Resource = "User", Action= "Post", AppICON="", WebICON="", APPURI="", WebURI="", IsActive=true, Notify=false, UpdatedOn = System.DateTime.Now },
            new Permission { PermissionId=4, Resource = "User", Action= "Put", AppICON="", WebICON="", APPURI="", WebURI="", IsActive=true, Notify=false, UpdatedOn = System.DateTime.Now },
            new Permission { PermissionId=5, Resource = "User", Action= "Delete", AppICON="", WebICON="", APPURI="", WebURI="", IsActive=true, Notify=false, UpdatedOn = System.DateTime.Now },
        };
    
        context.Permission.AddRange(permissions);
        context.Database.ExecuteSqlRaw(@"SET IDENTITY_INSERT [dbo].[Permission] ON");
        context.SaveChanges();
        context.Database.ExecuteSqlRaw(@"SET IDENTITY_INSERT [dbo].[Permission] OFF");
        context.Database.CommitTransaction();
    }
    

    变化:

    1. 首先删除了SaveChanges(),因为它根本不需要。
    2. Permission 数组初始化后的分号。
    3. ExecuteSqlRaw 调用而不是过时的ExecuteSqlCommand
    4. context.Database.CommitTransaction(); 提交更改。当然也必须考虑处理异常和事务回滚。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-03
      • 2018-02-16
      • 1970-01-01
      相关资源
      最近更新 更多