【问题标题】:Can't SaveChanges with Entity Framework in ASP.Net MVC 3 project无法在 ASP.Net MVC 3 项目中使用实体框架保存更改
【发布时间】:2012-08-16 13:06:31
【问题描述】:

学习 asp.net mvc 3 + EF 代码优先。我对两者都很陌生。我的例子是微不足道的,但我仍然无法让它工作。遗漏了一些简单而明显的东西......

我有课:

 public class Product
 {
    [HiddenInput(DisplayValue = false)]
    public int ProductID { get; set; }

    [Required(ErrorMessage = "Please enter a product name")]
    public string Name { get; set; }

    [Required(ErrorMessage = "Please enter a description")]
    [DataType(DataType.MultilineText)]
    public string Description { get; set; }

    [Required]
    [Range(0.01, double.MaxValue, ErrorMessage = "Please enter a positive price")]
    public decimal Price { get; set; }

    [Required(ErrorMessage = "Please specify a category")]
    public string Category { get; set; }
}

还有一个DbContext

public class EFDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }
}

还有一个存储库:

public class EFProductRepository : IProductRepository
{
    private EFDbContext context = new EFDbContext();

    public IQueryable<Product> Products
    {
        get
        {
            return context.Products;
        }
    }

    public void SaveProduct(Product product)
    {
        if (product.ProductID == 0)
            context.Products.Add(product);

        context.SaveChanges();
    }
}

mvc 控制器:

public class AdminController : Controller
{
    private IProductRepository repository;

    public AdminController(IProductRepository repo)
    {
        repository = repo;
    }

    public ViewResult Index()
    {
        return View(repository.Products);
    }

    public ViewResult Edit(int productId)
    {
        Product product = repository.Products.FirstOrDefault(p => p.ProductID == productId);
        return View(product);
    }

    [HttpPost]
    public ActionResult Edit(Product product)
    {
        if (ModelState.IsValid)
        {
            repository.SaveProduct(product);
            TempData["message"] = string.Format("{0} has been saved", product.Name);
            return RedirectToAction("Index");
        }
        else
        {
            // there is something wrong with the data values
            return View(product);
        }
    }
}

它让我查看产品列表,打开编辑视图,根据属性集验证所有内容...

当我保存经过验证的更改时,它会转到 Http Post Edit 方法并生成必要的 SaveChanges()

它不会抛出任何异常,它会继续并将我重定向到产品列表。

编辑的项目保持不变。

底层数据库(通过web.config 中的connectionstrings 连接)也保持不变。

【问题讨论】:

  • 试图找出我是否使用了不同的上下文...如果在两种不同的Edit 方法中检查,我的AdminController 中的repository 似乎有不同的GetHashCode()... .不知道它是否会说smth
  • 我使用 Ninject(也在学习 DI)
  • ProductID的默认值不会是Int32.MinValue,而不是0吗?此外,您如何以及何时将存储库传递给 AdminController 构造函数?
  • 即便如此,也并非如此,因为我只尝试编辑现有行

标签: c# asp.net-mvc-3 entity-framework ef-code-first savechanges


【解决方案1】:

您需要附加在EF外部创建的实体实例,并让EF知道它已被修改。

public void SaveProduct(Product product)
{
    if (product.ProductID == 0)
    {
        context.Products.Add(product);
    }
    else
    {
        context.Products.Attach(product);
        context.Entry(product).State = EntityState.Modified;
    }

    context.SaveChanges();
}

【讨论】:

  • 为什么说它是在EF外部创建的?
  • Edit "Get-request" 方法中,我让实体像这样Product product = repository.Products.FirstOrDefault(p =&gt; p.ProductID == productId) 进行编辑。它来自 EF 上下文
  • @horgh MVC 模型绑定器在调用Edit 方法时创建Product 的新实例。记住网络是少状态的。 GetPost 请求不会发生在同一个控制器实例中。
  • 那么,在这种情况下使用Attach 一定很常见吧?还是整体上有更好的方法?
  • @horgh 正确的方法是使用 ViewModel 与视图交互并将它们来回映射到控制器中的模型实例。
【解决方案2】:

您应该将Attach Product 实例添加到SaveChanges 之前的上下文中

public void SaveProduct(Product product)
{
    if (product.ProductID == 0)
        context.Products.Add(product);
    else
    {    
        context.Products.Attach(product);
        context.Entry(product).State = EntityState.Modified;
    }
    context.SaveChanges();
}

【讨论】:

    【解决方案3】:

    确实,你应该附上。

    假设您调用了 Edit(1)。您的控制器将从您的数据库中加载 ID = 1 的 Product 并根据其属性(无论如何您在视图中声明的属性)生成一个 HTML 视图。 一旦你离开 Edit(int productId) 方法并且你看到你的视图出现在你的浏览器中,你的 DbContext 已经丢失了具有该 ID 的产品;它已经超出范围。 如果您随后对产品进行更改并提交表单,ASP MVC 将根据您的表单字段(以及其他内容)拼凑一个新的产品对象,并将该对象传递给 Edit(Product product) 方法。 由于这是一个全新的 Product 对象并且旧的 Product 对象无论如何都超出了范围,您 DbContext 不知道新 Product 与您的数据库的关系:它是一个新对象,它是一个现有对象,如果它存在的话有什么变化吗? 如果您附加 Product 对象并将其状态设置为已修改,则 DbContext 可以开始检查哪些属性已更改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多