在ASP.Net MVC 3项目中无法使用Entity Framework进行SaveChanges

学习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 Products { get; set; } } 

和一个存储库:

 public class EFProductRepository : IProductRepository { private EFDbContext context = new EFDbContext(); public IQueryable 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); } } } 

它让我看到产品列表,打开编辑视图,根据属性集validation所有内容……

当我保存经过validation的更改时,它将转到Http Post Edit方法并进行必要的SaveChanges()

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

编辑的项目保持不变。

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

您需要附加在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(); } 

您应该在SaveChanges之前Attach Product实例Attach到上下文

 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(); } 

的确,你应该附上。

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