【问题标题】:C# ASP.NET MVC Code First Not Saving ChangesC# ASP.NET MVC 代码首先不保存更改
【发布时间】:2013-06-02 07:26:25
【问题描述】:

我有一个非常简单的模型:

public class Item : DbEntity
{
    public string Name {get;set;}
    public int Quantity {get;set;}
    public virtual Category Category {get;set;}
}

public class Category : DbEntity
{
    public string Name {get;set;}
}

我使用以下方法保存并提交对数据库的更改:

public void SaveEntity<TEntity>(TEntity entity) where TEntity : DbEntity
{
    if (entity.Id.Equals(Guid.Empty))
        _context.Set<TEntity>().Add(entity);
    else
        _context.Entry(entity).State = System.Data.EntityState.Modified;

    _context.SaveChanges();
}

public void DeleteEntity<TEntity>(TEntity entity) where TEntity : DbEntity
{
     _context.Set<TEntity>().Remove(entity);
     _context.SaveChanges();
}

这些保存和删除方法驻留在 Repository 中,这个 Repository 是 Ninjected,所以它应该在整个应用程序生命周期内保持不变的状态。这是一种久经考验的方法,它一直对我有用。现在出于某种原因,当我这样做时:

[HttpPost]
public ActionResult Edit(MenuItemViewModel vm)
{
    if (ModelState.IsValid)
    {
        // TODO: Add ViewModel Logic
        vm.MenuItem.Category = _repository.Categories.FirstOrDefault(x => x.Id.Equals(vm.SelectedCategory));

    try
    {
        // TODO: Add Save Logic
            _repository.SaveEntity(vm.MenuItem);

            TempData["success"] = true;
            TempData["message"] = String.Format("Saved {0} Successfully", vm.MenuItem.Description);
    }
    catch (Exception ex)
    {
             TempData["error"] = true;
             TempData["message"] = "Error Occured";
    }

    return _redirectTo;
    }

    return View("Shape", vm);
}

视图部分很简单,只是NameQuantity 的一些字段,Category 是一个Drop Down 框,其中包含所有类别名称为Text 和id 为Value,这得到发回存储库所在的服务器并收集新的Category 并将其分配给实体。

由于某种原因,这只是没有对数据库进行任何更改,前后都有断点,当我在检查数据库后中断时,它没有改变!

任何人都可以看到阻止它更新的愚蠢的小错误。

编辑

刚刚读到这个StackOverflow Post,我拿起了上面说的部分,你先附加它然后编辑它,因为当调用附加时,你用Unchanged状态调用它,然后当你修改它时,当您致电SaveChanges() 时,更改将被保存。

这有关系吗?!

更新
好吧,一些有趣的消息,我通过SaveEntity 方法,在我通过SaveChanges() 之后我再次检查上下文,它显示它已被更新?!我重定向到另一个控制器和操作的事实是否会影响结果或表修改?我认为问题不在于SaveEntity 方法!!

最新更新

我更改了Item 的型号并简单地添加了public Guid CategoryId {get;set;} 行,它只是更改了Category 以打开Cascade On Delete。现在当我尝试SaveChanges时出现此错误:

发生了参照完整性约束冲突:定义参照约束的属性值在关系中的主体对象和依赖对象之间不一致。

【问题讨论】:

  • 你确定在调用DbContext.Entry(object)之前不需要使用DbContext.Attach吗?
  • 仓库被ninject调用时实例化上下文。所以它应该已经存在了??
  • 我确信 Ninject 不会将对象附加到您的 DbContext。
  • 对不起...值得一试...
  • 是的,没问题,绝对值得一试!

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


【解决方案1】:

在 SaveEntity 中,如果 Id 不等于 Guid.Empty,则不会将项目附加到上下文,只是将状态设置为已修改。试试:

public void SaveEntity<TEntity>(TEntity entity) where TEntity : DbEntity
{
    if (entity.Id.Equals(Guid.Empty))
    {
        _context.Set<TEntity>().Add(entity); // Automatically sets state to Added
    }
    else 
    {
        _context.Set<TEntity>().Attach(entity);
        _context.Entry(entity).State = System.Data.EntityState.Modified;
    }

    _context.SaveChanges();
}

另外,对于 DeleteEntity,请尝试附加和删除:

public void DeleteEntity<TEntity>(TEntity entity) where TEntity : DbEntity
{
    _context.Set<TEntity>().Attach(entity); // Attaches entity with state Unchanged
    _context.Set<TEntity>().Remove(entity); // Changes entity state to Deleted
    _context.SaveChanges();
}

关键是在 ASP.NET 等断开连接的环境中,从帖子返回的模型不会附加到上下文,因此需要重新附加才能处理它。

作为测试,请在调用 SaveChanges 之前检查现有代码中实体的状态,它可能是 Unchanged 意味着不会对其采取任何操作。

【讨论】:

  • 如何使用智能感知在调试中找到实体的状态?还是我应该只写一行询问它的状态?
  • 我写了一行var entryState = _context.Entry(entity).State;,上面写着Modified,我从来不用附加,它一直有效,这很奇怪!
  • 可以设置断点,当断点被命中时,将鼠标悬停在变量(实体)上。
【解决方案2】:

所以,为了解决这个问题,我将 Item 实体更改为:

public class Item : DbEntity
{
    public string Name {get;set;}
    public int Quantity {get;set;}

    public Guid? CategoryId {get;set;}
    public virtual Category Category {get;set;}
}

这基本上使更改Category 变得更加容易和快捷,因为您不必再​​次调用数据库。 ? 使其成为可空属性,将 Cascade Delete 设置为 No Action,因此当您删除 Item 时,它不会烦人地消失并删除关联的 Categories

我仍然不知道为什么原来的方式行不通,它在过去已经完成并且它曾经否定必须放置public Guid? CategoryId {get;set;},因为它会设置可为空的属性并且已经创建了一个Category_Id 字段.但是嘿嗬,这就是它想要的样子,那我就去打球了!!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-03
    • 2019-08-08
    • 2014-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多