尝试更新实体时出错

时间:2012-05-23 10:29:30

标签: asp.net-mvc entity-framework dbcontext

我在我的MVC 3应用程序中使用实体框架4.3,在尝试更新实体时(创建和删除工作正常)我收到此错误:

  

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

当我进入调试模式时,我在[HttpPost]方法上看到没有提供Feed ID:

public ActionResult Edit(Feed feed)
    {
        if (ModelState.IsValid)
        {
            db.Entry(feed).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        ViewBag.FolderId = new SelectList(db.Folders, "FolderId", "Name", feed.FolderId);
        return View(feed);
    }

虽然在正常的Get方法中传递了id。那些是我的实体

饲料:

public class Feed
{
    [ScaffoldColumn(false)]
    public int FeedId { get; set; }

    [StringLength(150, ErrorMessage = "The {0} must be less then {1} charecters")]
    public string Title { get; set; }

    [ScaffoldColumn(false)]
    public string Description { get; set; }

    [Required(ErrorMessage = "you must enter a valid link")]
    [StringLength(500, ErrorMessage = "The {0} must be less then {1} characters long.")]
    public string LinkUrl { get; set; }

    [ScaffoldColumn(false)]
    public DateTime PublishDate { get; set; }

    [ScaffoldColumn(false)]
    public string Image { get; set; }

    [ForeignKey("Folder")]
    [Required(ErrorMessage="you must choose a folder")]
    public int FolderId { get; set; }

    public virtual Folder Folder { get; set; }

    public Feed()
    {
        PublishDate = new DateTime(2012, 1, 1);
    }
}

文件夹:

public class Folder
{    
    public int FolderId { get; set; }

    [Required(ErrorMessage = "you must enter a folder name")]
    [StringLength(150, ErrorMessage = "the {0} must be less then {1} charecters")]
    public string Name { get; set; }
}

我已经找到了一个解决方案,但没有一个能够工作,就像尝试刷新方法一样,DbContext中不存在或在FeedId和FolderId上定义[Key]属性。

4 个答案:

答案 0 :(得分:0)

您不应手动维护实体状态 - 更改跟踪应由上下文执行。

您正在使用视图模型并假设它应该附加到数据库。

您需要执行类似..,

的操作
Feed DbFeed = DBSet.Where(f => f.id = feed.Id);
DbFeed.Property = NewValue;
db.SaveChanges();

(原谅可能是错误的语法 - 默认情况下我在VB中工作)

也就是说,从DB Context获取Feed对象的新实例,然后对您给出的对象执行更改。

这是因为上下文实际上并没有给你一个简单的Feed对象,而是一个包装它并具有相同属性的匿名类型。包装器会覆盖您的方法并检测属性更改,这是它维护状态的方式。

从视图中返回的Feed对象不包含此包装,因此存在问题

答案 1 :(得分:0)

实体框架跟踪对象,您从视图中获取的Feed未跟踪。这种情况的模式是从数据库中获取要更新的对象,然后调用UpdateModel,它将从未跟踪的实体应用更改到您跟踪的实体,然后您可以保存...

    if (ModelState.IsValid)
    {
        var trackedEntity = db.Find(feed.Id)
        UpdateModel(trackedEntity);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

答案 2 :(得分:0)

显然

但是在我的模型中放置[ScaffoldColumn(false)]属性并没有在我的视图中创建它,并且没有传递id。

我将@Html.HiddenFor(model => model.FeedId)添加到我的模型中,并解决了这个问题。

答案 3 :(得分:0)

显然你遇到了并发问题。 您的更新状态应该以:

运行
   UPDATE tableA SET colA = 'value' WHERE colX1 = 'compare1' AND colX2 = 'compare2';

colXn可能是您的主键等,也可能是您正在使用的每个列。如果您没有处理并发,如果有人在您获取数据的同时,在您之前更改并保存数据,则WHERE语句将永远不会匹配,因为您正在更新的记录信息已经包含新信息。 / p>