0

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

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

当我进入调试模式时,我看到在 [HttpPost] 方法上没有提供提要 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

4 回答 4

0

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

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

于 2012-05-24T08:33:39.877 回答
0

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

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

你需要做类似的事情..,

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

(请原谅可能不正确的语法 - 我默认在 VB 中工作)

也就是说,从 DB 上下文中获取 Feed 对象的新实例,然后对给定的对象执行更改。

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

您从视图返回的提要对象不包含此包装器,因此存在问题

于 2012-05-23T10:52:20.830 回答
0

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

    if (ModelState.IsValid)
    {
        var trackedEntity = db.Find(feed.Id)
        UpdateModel(trackedEntity);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
于 2012-05-23T10:53:49.440 回答
0

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

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

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

于 2014-11-26T13:42:20.437 回答