Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't SaveChanges with Entity Framework in ASP.Net MVC 3 project

Studying asp.net mvc 3 + EF code-first. I am new to both. My example is trivial, but I still can't make it work. Missing something simple and obvious...

I've got a class:

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

and a DbContext:

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

and a repository:

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

The mvc controller:

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

It lets me see the list of products, opens the edit view, validates everything according to the set of attributes...

When I save validated changes it goes to the Http Post Edit method and makes the necessary SaveChanges().

It doesn't throw any exceptions, it goes on and redirect me to the list of products.

The edited item stays unchanged.

The underlying database (connected through connectionstrings in web.config) stays unchanged as well.

like image 588
horgh Avatar asked Aug 21 '12 08:08

horgh


Video Answer


2 Answers

You need to attach the entity instance created outside EF and let EF know that it has been modified.

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();
}
like image 168
Eranga Avatar answered Oct 27 '22 00:10

Eranga


You should Attach the Product instances to the context before 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();
}
like image 34
Charlie Avatar answered Oct 27 '22 00:10

Charlie