26

I've got an MVC web application that uses SQL Server 2008 as a back end database along with the Entity Framework. The application is working fine and pulling data from the database just fine. My problem is, when it does an update to the data, it doesn't appear to be saving it. I am using the follow function:

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

        context.SaveChanges(); // Breakpoint here
    }

This function is defined in my repository code. I set a breakpoint on the line commented above and the application is breaking at the line, so I know its hitting that line and the changes are all good in the context object. No error occurs, EF simply isn't saving the changes for some reason.

I believe my connection string is correct, since its pulling the data just fine, but here it is just in case:

<connectionStrings>
    <add name="EFDbContext" connectionString="Data Source=localhost;Initial Catalog=WarehouseStore;Integrated Security=True;Pooling=False" providerName="System.Data.SqlClient"/>
</connectionStrings>

Anyone have any ideas on what could cause this?

Icemanind
  • 47,519
  • 50
  • 171
  • 296
  • 1
    assuming you are running against SQL Server :-) have you turned on SQL profiler and see if EF is sending any query to the DB? there should just before any savechanges are done be a login entry in profiler from EF. – Ricky Gummadi Mar 04 '12 at 22:04
  • 1
    Have you checked if you hitting `context.Products.Add(product);` If not, nothing is being saved. – veblock Mar 04 '12 at 22:09
  • @veblock - I don't have the view for adding products done yet, so I can't test that part yet – Icemanind Mar 04 '12 at 22:17

6 Answers6

51

If you are after the insert/update functionality you have to cover both cases:

if (product.ProductID == 0)
{
    context.Entry(product).State = EntityState.Added;
}
else
{
    context.Entry(product).State = EntityState.Modified;
}
context.SaveChanges();
veblock
  • 1,904
  • 18
  • 10
  • 1
    Is there a reason that EF doesnt know this with out being told... after all I called the add method. It works on the edit existing – Chad Jul 12 '12 at 19:29
  • 2
    When you edit existing one, you get it from EF first, so EF tracks the state of the object. When you're adding a new one, you create the object outside of EF, hence when you're adding it, you have to explicitly tell EF to add it. – veblock Jul 12 '12 at 22:08
  • I have looked everywhere and didn't find what i am looking for, i am doing exaclty the same thing when trying to change password. But my changes are not accessible before i restart my solution. It is EF6 and MVC5 asp.net Please help. – Zia Ul Rehman Mughal Dec 10 '15 at 17:44
6

Thanks to @veblok I found the solution to my issue. There is an option in the DbContext class to prevent EF to track object by default. Once removed it EF started behaving as expected.

 public class My Context : DbContext {
  public MyContext()
  {
        // REMOVE this or use veblok's solution
        this.Configuration.AutoDetectChangesEnabled = false;            
  }
  ...
 }
Stefano Altieri
  • 4,550
  • 1
  • 24
  • 41
  • 2
    the `AutoDetectChangesEnabled` property can greatly improve performance (and memory footprint) for read only queries - so if you find this in your code base don't remove it without checking. if you're just doing a simple update inside a method that is doing a complex read then you may want to create a new data context for the update – Simon_Weaver Jan 17 '17 at 04:34
2

you can use Create method of context : use this method generally when you have a related entity

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

            context.Products.Add(product);
    }

    context.SaveChanges(); // Breakpoint here
}
HamidReza
  • 1,726
  • 20
  • 15
0

I had the same problem. context.Entry(product).State = EntityState.Modified; gave me an error. Interesting solution is to use DbSetMigrationsExtensions.AddOrUpdate() Method. This Method is part of DbSetMigrationExtensions and you need to specify the following namespace in order to use this extension method:

using System.Data.Entity.Migrations;

public void SaveProduct(Product product)
    {
        context.Set<Product>().AddOrUpdate(product);

        context.SaveChanges();
    }
mirushaki
  • 897
  • 1
  • 10
  • 13
  • It is not exactly designed for this purpose, but it may work for your purpose... See https://stackoverflow.com/questions/31272455/ef-is-it-ok-to-use-dbsett-addorupdate-outside-of-migrations – Roland Pihlakas Jan 15 '20 at 07:36
0

My issue was slightly different. My model said the DB was assigning the key, but I was actually creating it in my controller and passing it. I commented out the line below and everything started working:

enter image description here

Best of luck to anyone else who may run into this. Was a bugger to find!

flashsplat
  • 433
  • 3
  • 13
-3

Be sure your table has a primary key.

If so, you will find this line in the dbcontext

entity.HasNoKey();

benhorgen
  • 1,928
  • 1
  • 33
  • 38