代码之家  ›  专栏  ›  技术社区  ›  strongopinions

实体框架:“存储更新、插入或删除语句影响了意外的行数(0)。”[已关闭]

  •  291
  • strongopinions  · 技术社区  · 16 年前

    Store update、insert或delete语句影响了意外的行数(0)。自加载实体后,实体可能已被修改或删除。刷新ObjectStateManager条目。

    45 回复  |  直到 8 年前
        1
  •  410
  •   Jens Kloster    12 年前

    我遇到了这个问题,这是由于没有设置实体的ID(key)字段造成的。因此,当上下文去保存数据时,它找不到ID=0。确保在update语句中放置断点,并验证已设置实体的ID。

    我有一个确切的问题,是因为忘记包含隐藏的ID 在.cshtml编辑页面中输入

        2
  •  210
  •   Daniel Sam    11 年前

    这是乐观并发特性的副作用。

    无法100%确定如何在Entity Framework中打开/关闭它,但基本上它告诉您的是,从您从数据库中获取数据到您保存更改时,其他人已经更改了数据(这意味着在您保存数据时,0行实际上得到了更新)。用SQL术语来说,它们的 update 查询的 where 子句包含该行中每个字段的原始值,如果0行受到影响,它就知道出了问题。

    它背后的思想是,您不会最终覆盖应用程序不知道已经发生的更改—这基本上是.NET在您的所有更新中引入的一个小安全措施。

        3
  •  119
  •   Ben    14 年前

    哇,有很多答案,但当我做了一些其他人都没有提到的稍有不同的事情时,我犯了这个错误。

    长话短说,如果您创建一个新对象,并告诉EF使用 EntityState.Modified

    MyObject foo = new MyObject()
    {
        someAttribute = someValue
    };
    
    context.Entry(foo).State = EntityState.Modified;
    context.SaveChanges();
    

    是的,这看起来很愚蠢,但它的出现是因为所讨论的方法过去有 foo 传递给它之前已创建,现在只有 someValue 福 它本身

    容易修复,只要改变 到 EntityState.Added

    context.MyObject.Add(foo);
    
        4
  •  23
  •   Leniel Maccaferri    14 年前

    @Html.HiddenFor(model => model.UserProfile.UserId)

    用于更新对象的主键!我倾向于忘记这个简单但非常重要的事情!

    顺便说一句: HiddenFor 是针对ASP.NET MVC的。

        5
  •  16
  •   dotNetE    13 年前
        6
  •  15
  •   Pure.Krome    15 年前

    该问题由以下两种原因之一引起:-

    1. Concurrency Mode: Fixed
    2. 您试图更新或删除一行,但该行不存在。另一个例子是,有人在检索然后保存之间更改数据(在本例中为删除),或者您尝试更新一个非标识字段(即。 StoreGeneratedPattern = Computed )而这一行并不存在。
        7
  •  12
  •   innominate227    10 年前

    解决方案是在插入之前截断DateTime.Now的毫秒数。

        8
  •  10
  •   Community Mohan Dere    9 年前

    answer 帮助找到了解决办法。

    我的模型使用的是 Bind(Exclude)

    namespace OrderUp.Models
    {
    [Bind(Exclude = "OrderID")]
    public class Order
    {
        [ScaffoldColumn(false)]
        public int OrderID { get; set; }
    
        [ScaffoldColumn(false)]
        public System.DateTime OrderDate { get; set; }
    
        [Required(ErrorMessage = "Name is required")]
        public string Username { get; set; }
        }
    }   
    
        9
  •  10
  •   Bilel Chaouadi    7 年前
        10
  •  8
  •   Arun Aravind    13 年前

    编辑时,将实体的id或主键作为隐藏字段包含在视图中

    即

          @Html.HiddenFor(m => m.Id)
    

        11
  •  8
  •   Si-N    12 年前

    我也遇到了这个错误。这个问题原来是由我试图保存到的表上的触发器引起的。触发器使用了“而不是INSERT”,这意味着曾经向该表插入过0行,因此出现了错误。幸运的是,在五月的情况下,触发器功能是不正确的,但我想它可能是一个有效的操作,应该以某种方式在代码中处理。希望有一天这能帮助别人。

        12
  •  8
  •   avenmore    11 年前

    在从模型优先更改为代码优先后,我开始出现此错误。我有多个线程更新数据库,其中一些线程可能更新同一行。我不知道为什么首先使用模型时没有问题,假设它使用不同的并发默认值。

    using System.Data.Entity.Core.Objects;
    using System.Data.Entity.Infrastructure;
    
    public class MyDbContext: DbContext {
    ...
            public int SaveChanges(bool refreshOnConcurrencyException, RefreshMode refreshMode = RefreshMode.ClientWins) {
                try {
                    return SaveChanges();
                }
                catch (DbUpdateConcurrencyException ex) {
                    foreach (DbEntityEntry entry in ex.Entries) {
                        if (refreshMode == RefreshMode.ClientWins)
                            entry.OriginalValues.SetValues(entry.GetDatabaseValues());
                        else
                            entry.Reload();
                    }
                    return SaveChanges();
                }
            }
    }
    

    然后叫 SaveChanges(true) 如适用。

        13
  •  7
  •   Paulo    15 年前

    您需要显式地包含主键的边界字段。如果您不希望用户看到主键,则必须通过css将其隐藏:

        <asp:BoundField DataField="Id_primary_key" ItemStyle-CssClass="hidden" 
    HeaderStyle-CssClass="hidden" />
    

    其中“hidden”是css中的一个类,其显示设置为“none”。

        14
  •  7
  •   Tomo    8 年前

    [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None)] 在我的情况下,我做了一个诀窍:

    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    
    
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int? SomeNumber { get; set; }
    
        15
  •  6
  •   combatc2    8 年前

        16
  •  5
  •   Manoj    13 年前

    只需确保表和表单都更新了主键和edmx。

    我发现更新过程中出现的任何错误通常是因为: -表中没有主键 @Html.HiddenFor(m=>m.Id )

        17
  •  5
  •   Rusty Nail    13 年前

    我也有这个错误。在某些情况下,实体可能不知道您使用的实际数据库上下文,或者模型可能不同。为此,设置:EntityState.Modified;添加到EntityState;

    if (ModelState.IsValid)
    {
    context.Entry(yourModelReference).State = EntityState.Added;
    context.SaveChanges();
    }
    

    希望这有帮助。

        18
  •  5
  •   wickjon    11 年前
      @Html.HiddenFor(model => model.RowVersion)
    

    这解决了我的问题

        19
  •  4
  •   ajaysinghdav10d dhilt    11 年前

    在我的例子中,我试图更新主键,这是不允许的。

        20
  •  4
  •   Ogglas    8 年前

    async

    偶尔出现的错误:

    [Authorize(Roles = "Admin")]
    [HttpDelete]
    [Route("file/{id}/{customerId}/")]
    public async Task<IHttpActionResult> Delete(int id, int customerId)
    {
        var file = new Models.File() { Id = id, CustomerId = customerId };
        db.Files.Attach(file);
        db.Files.Remove(file);
    
        await db.SaveChangesAsync();
    
        return Ok();
    }
    

    一直在工作:

    [Authorize(Roles = "Admin")]
    [HttpDelete]
    [Route("file/{id}/{customerId}/")]
    public IHttpActionResult Delete(int id, int customerId)
    {
        var file = new Models.File() { Id = id, CustomerId = customerId };
        db.Files.Attach(file);
        db.Files.Remove(file);
    
        db.SaveChanges();
    
        return Ok();
    }
    
        21
  •  3
  •   Tony    14 年前

    当我删除数据库中的一些行(在循环中)并在同一个表中添加新行时,我遇到了这个错误。

    我的解决方案是,在每个循环迭代中动态地创建一个新的上下文

        22
  •  3
  •   Bo Persson Touseef    13 年前
        public void Save(object entity)
        {
            using (var transaction = Connection.BeginTransaction())
            {
            try
                    {
                        SaveChanges();
                        transaction.Commit();
                    }
                    catch (OptimisticConcurrencyException)
                    {
                        if (ObjectStateManager.GetObjectStateEntry(entity).State == EntityState.Deleted || ObjectStateManager.GetObjectStateEntry(entity).State == EntityState.Modified)
                            this.Refresh(RefreshMode.StoreWins, entity);
                        else if (ObjectStateManager.GetObjectStateEntry(entity).State == EntityState.Added)
                            Detach(entity);
                        AcceptAllChanges(); 
                        transaction.Commit();
                    }
            }
        }
    
        23
  •  3
  •   Serj Sagan    12 年前

    如果您试图插入一个独特的约束条件,也会发生这种情况,即如果您每个雇主只能有一种类型的地址,并且您尝试在同一雇主中插入第二种相同类型的地址,您将遇到相同的问题。

    或

    如果指定给的所有对象特性的值与以前相同,也可能发生这种情况。

            using(var db = new MyContext())
            {
                var address = db.Addresses.FirstOrDefault(x => x.Id == Id);
    
                address.StreetAddress = StreetAddress; // if you are assigning   
                address.City = City;                   // all of the same values
                address.State = State;                 // as they are
                address.ZipCode = ZipCode;             // in the database    
    
                db.SaveChanges();           // Then this will throw that exception
            }
    
        24
  •  2
  •   Mubarak    15 年前

    我希望我说清楚了。

        25
  •  2
  •   Andrew    13 年前

    context.Users.Attach(orderer);
    

    具有

    if (orderer.Id > 0) {
        context.Users.Attach(orderer);
    }
    
        26
  •  2
  •   Ali    12 年前

    我也有同样的问题。但这是由于我自己的错误。实际上我是在保存一个对象而不是添加它。这就是冲突。

        27
  •  2
  •   rism    12 年前

    在Sql Server环境中调试此问题的一种方法是使用Sql Server副本附带的Sql Profiler,或者如果使用的是Express版本,则通过以下链接从CodePlex免费获取一份Express Profiler副本:

    Express Profiler

    通过使用Sql Profiler,您可以访问EF发送到DB的任何内容。就我而言,这相当于:

    exec sp_executesql N'UPDATE [dbo].[Category]
    SET [ParentID] = @0, [1048] = NULL, [1033] = @1, [MemberID] = @2, [AddedOn] = @3
    WHERE ([CategoryID] = @4)
    ',N'@0 uniqueidentifier,@1 nvarchar(50),@2 uniqueidentifier,@3 datetime2(7),@4 uniqueidentifier',
    @0='E060F2CA-433A-46A7-86BD-80CD165F5023',@1=N'I-Like-Noodles-Do-You',@2='EEDF2C83-2123-4B1C-BF8D-BE2D2FA26D09',
    @3='2014-01-29 15:30:27.0435565',@4='3410FD1E-1C76-4D71-B08E-73849838F778'
    go
    

    我将其复制粘贴到Sql Server中的查询窗口中并执行它。果不其然,尽管它运行了,但0条记录受此查询的影响,因此EF返回了错误。

    但这并不是EF的错,而是视图控制器中出现了一个错误的null合并“?”语句,该语句正在向数据层发送无用信息。

        28
  •  2
  •   J. Polfer    10 年前

    以上答案都没有完全涵盖我的情况和解决办法。

    MVC5控制器中引发错误的代码:

            if (ModelState.IsValid)
            {
                db.Entry(object).State = EntityState.Modified; 
                db.SaveChanges(); // line that threw exception
                return RedirectToAction("Index");
            }
    

    您可以通过A)修改save调用来添加对象,或者B)只需在编辑时不更改主键即可解决此问题。我做了(B)。

        29
  •  2
  •   Mahesh    10 年前

    当被接受的答案是“我的朋友” 它不会覆盖应用程序不知道发生的更改 “,我对此表示怀疑,因为我的对象是新创建的。但后来发现,有一个 INSTEAD OF UPDATE, INSERT- TRIGGER 附加到正在更新同一表的计算列的表。

    一旦我把这个改成 AFTER INSERT, UPDATE

        30
  •  2
  •   R. Salisbury    9 年前

    这种情况发生在我身上是因为datetime和datetime2之间不匹配。奇怪的是,在测试人员发现问题之前,它工作正常。My Code First模型包含日期时间作为主键的一部分:

    [Key, Column(Order = 2)]  
    public DateTime PurchasedDate { get; set; } = (DateTime)SqlDateTime.MinValue;
    

    生成的列是datetime列。调用SaveChanges时,EF生成以下SQL:

    -- Region Parameters
    DECLARE @0 Int = 2
    DECLARE @1 Int = 25
    DECLARE @2 Int = 141051
    DECLARE @3 DateTime2 = '2017-07-27 15:16:09.2630000' --(will not equal a datetime value)
    -- EndRegion
    UPDATE [dbo].[OrganizationSurvey]
    SET [OrganizationSurveyStatusId] = @0
    WHERE ((([SurveyID] = @1) AND ([OrganizationID] = @2)) AND ([PurchasedDate] = @3))
    

    [Key, Column(Order = 2, TypeName = "DateTime2")]  
    public DateTime PurchasedDate { get; set; } = (DateTime)SqlDateTime.MinValue;