存储更新,插入或删除语句影响了意外的行数(0)EntityFramework

时间:2013-11-18 09:56:50

标签: c# asp.net asp.net-mvc entity-framework

当我尝试保存对上下文所做的更改时,我一直收到以下错误:

  

存储更新,插入或删除语句会影响意外   行数(0)。自那以后,实体可能已被修改或删除   实体已加载。刷新ObjectStateManager条目。

我有以下课程:

public class Person : IPerson
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string Name
    {
        get
        {
            return FirstName + " " + LastName;
        }
        set{}
    }

    public string Email { get; set; }
    public DateTime? LastModified { get; set; }
    public virtual ICollection<Result> Results { get; set; }
}

用户配置

public class UserProfile : Person
{
    public UserProfile()
    {
        Faculty = new Faculty();
        Projects = new Collection<Project>();
        Results = new Collection<Result>();
    }
    public string UserName { get; set; }
    public string CNP { get; set; }
    public virtual Faculty Faculty { get; set; }
    public virtual ICollection<Project> Projects { get; set; }
}

结果

public abstract class Result:INamedEntity
{
    protected Result()
    {
        ResultType = new ResultType();
    }
    public int Id { get; set; }
    public string Name{get;set;}
    public virtual ResultType ResultType { get; set; }
    public virtual ICollection<Person> People { get; set; }
    public DateTime? LastModified { get; set; }
}

使用以下方法向上下文添加值后

_ctx.Users.Single(u => u.Id == userId).Results.Add(result);

我在拨打_ctx.SaveChanges()

时收到错误消息

将我的功能更新为:

public bool Save()
{

    try
    {
        _ctx.SaveChanges();
    }
    catch (OptimisticConcurrencyException)
    {
        ((IObjectContextAdapter)_ctx).ObjectContext.Refresh(RefreshMode.ClientWins,_ctx.Users);
        ((IObjectContextAdapter)_ctx).ObjectContext.Refresh(RefreshMode.ClientWins,_ctx.Results);
        _ctx.SaveChanges();
    }
    return true;
}

但错误并未被发现。 谢谢

16 个答案:

答案 0 :(得分:40)

将此添加到您的edit.cshtml

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

我遇到了这个问题,发现该ID因为不在页面上而显示为0.

我的ViewModel上也有这个(我正在使用视图模型方法)

[HiddenInput(DisplayValue = false)]
[Key]
public int Id { get; set; }

答案 1 :(得分:13)

想出来。 问题是我们有两个人正在研究这个项目,我的同事创建了他自己的DBContext实例,他正在更新一个而另一个。因此,对于将来遇到此问题的人,请确保您的DBContext同时没有两个不同的实例

答案 2 :(得分:2)

您的异常意味着在您从数据库中获取数据并对其进行修改之间,您的数据已被更改。

默认情况下,实体框架实现乐观并发模型。这意味着在查询数据和更新数据之间,数据源中的数据不会保留锁定。 MSDN

如何在对象上下文中管理并发。MSDN

或者按照这个更新背景的答案。 StackOverflow

答案 3 :(得分:2)

对我来说问题是我没有正确设置动作绑定

public ActionResult Edit([Bind(Include = "VehicleID,Name,CreateDate,PowerPS,DrivenKM")] Car car)
    { ... }

VehicleID使用错误的标识符进行映射,因此Entity Framework始终将0作为主键。

答案 4 :(得分:1)

如果您遇到过这个问题并且没有上述解决方案帮助过您,也许您可​​以试试这个。我也遇到了这个奇怪的问题,我能够解决这个问题的方法是将一个字段设置为主键并让它自动递增或设置为Identity。假设您有Person表,并且您可能有personID,将其设置为主键并确保它自动递增。

答案 5 :(得分:1)

将以下重载添加到我的DbContext类:

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)

答案 6 :(得分:0)

存在冲突,因为您正在使用乐观锁定。使用ObjectStateManager条目解决并发问题,并再次保存更改。 MSDN网站中有一些示例代码。

答案 7 :(得分:0)

我在google时遇到过这种情况。我有相同的错误消息,但原因是我没有设置一些强制非空值。

也许这个发现对某人有帮助。

答案 8 :(得分:0)

我也遇到了这条错误消息。造成我错误的原因是主要/外键冲突。我已经将一些新数据推送到我的数据库中,并且我的外键值已关闭(我的上传脚本中的错误)。

使用SQL事件探查器来帮助跟踪有问题的插入脚本,这可能有助于您发现更新的问题。

希望这可以帮助其他有类似问题的人。

答案 9 :(得分:0)

谢谢特里, 我们加上这个: 在脚手架中不要将[必需]属性添加到您的Key / ID。 这会阻止您的上下文从网址中提取密钥/ ID。 也: 迁移后,我在脚手架控制器中发生了这种情况 其中包括模型上的新布尔字段。这些领域是 没有设定。

答案 10 :(得分:0)

确保从视图中将两个表的ID传递给模型。在您的情况下,它是表Person和UserProfile的关键。 如果您不需要在页面上显示ID,则可以添加 @ Html.HiddenFor(model =&gt; model.PersonId)和@ Html.HiddenFor(model =&gt; model.UserProfileId)

答案 11 :(得分:0)

我在创建项目时遇到了这个错误,甚至只是尝试进行简单的插入。

我们从预先存在的数据库生成EF模型,框架自动在多个字段上设置Entity Key = True

将除ID以外的所有内容设置为False解决了问题。

答案 12 :(得分:0)

我不知道到底出了什么问题,但我只是做了这些步骤并得到了解决。 (我希望你能够解决这个问题,因为我能够做到这一点)
步骤如下:
(1)根据您的edmx表和EF文件的DB上下文,使用脚手架添加新控制器。
(2)现在保存更改创建的问题是编辑方法。
(3)现在复制脚手架制作的编辑方法/整个控制器并将其粘贴到原始控制器中。
(4)现在只需构建程序, Voila 就可以了。

<强>更新
我发现,要从视图中编辑数据,必须发送所有字段以便再次写入控制器。如果在编辑时缺少实体表中的任何字段,则不允许编辑。特别是如果PK在Label中并发送到控制器进行编辑,那么它将生成此错误。

答案 13 :(得分:0)

在我的情况下,我有一个复合键,并试图更新它的一部分(3列构成一个复合键,其中我只更新第3列)但EF不允许更改相同的键值对象,我通过以下方式实现了更新记录:

Context.Database.ExecuteSqlCommand(udpateCommand);

答案 14 :(得分:0)

好吧,在使用Code First使用Entity Framework 6.13时,我也遇到了这种类型的并发错误。在我自己解决之前,我也挣了几个小时。所以它可以帮助那里的人。使用复合主键创建了一个表,今天我更改了表的结构,只使用了一个主键(使用AutoIncrement)而不是复合键,并通过使用fluent-api配置进行迁移来更新表。表已更新但主键未使用AutoIncrement更新,每当我尝试添加记录时,它都显示并发错误。因此,当我设置字段的自动增量并且错误消失了。希望,它有所帮助。

答案 15 :(得分:-1)

我修复了一些在尝试更新记录时给出相同错误消息的代码。我最初有以下代码:

[HttpPost]
    public ActionResult Edit(Project project)
    {
        if (ModelState.IsValid)
        {

            entity.Entry(project).State = EntityState.Modified;
            entity.SaveChanges();

            return RedirectToAction("Index", "Home");
        }
        return View(project);
    }

而不是以下代码

   [HttpPost]
    public ActionResult Edit(Project project)
    {
        if (ModelState.IsValid)
        {

            entity.Entry(project).State = EntityState.Added;
            entity.SaveChanges();

            return RedirectToAction("Index", "Home");
        }
        return View(project);
    }