C#ASP.NET MVC代码首先不保存更改

时间:2013-06-06 10:17:57

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

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

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框,其中包含所有类别名称{{1} }和id为Text,这将被发送回存储库所在的服务器并收集新的Value并将其分配给实体。

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

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

修改

请阅读此StackOverflow Post,我选择了所说的部分,然后先将其附加然后进行编辑,因为调用附加时,您将其称为Category状态,然后当您修改它,当您拨打Unchanged时,将保存更改。

这与它有什么关系吗?!

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

最新更新

我更改了SaveEntity的模型,只需添加行Item,只需更改public Guid CategoryId {get;set;}即可启用Category。现在,当我尝试Cascade On Delete

时,我收到此错误
  

发生了引用完整性约束违规:定义引用约束的属性值在关系中的主体和从属对象之间不一致。

2 个答案:

答案 0 :(得分:1)

所以,为了解决这个问题,我将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,因为它将设置可为空的属性并且已经创建了{{ 1}}字段。但嘿嘿,这就是它想成为的样子,然后我会打球!!

答案 1 :(得分:0)

在SaveEntity中,如果Id不等于Guid.Empty,则不将该项附加到上下文,仅将State设置为Modified。尝试:

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之前检查现有代码中实体的状态,并且它可能不变,意味着不会对其执行任何操作。