InsertOrUpdateGraph, SyncObjectGraph and SyncObjectsStatePreCommit

Mar 9, 2015 at 4:28 PM
Edited Mar 9, 2015 at 9:22 PM
I have 2 classes:
  • Log
  • LogSeverity
Each log has a LogSeverity.

When I start my application, I get all LogSeverity with .AsNoTracking() as I create a Unit of Work and Context each time I need to call the database. I have "using" everywhere in order to keep my context, UoW and services open the sortest time possible.

When I save logs, I sometimes get the following error:
Saving or accepting changes failed because more than one entity of type 'Entities.Models.LogSeverity' have the same primary key value. Ensure that explicitly set primary key values are unique. Ensure that database-generated primary keys are configured correctly in the database and in the Entity Framework model. Use the Entity Designer for Database First/Model First configuration. Use the 'HasDatabaseGeneratedOption" fluent API or 'DatabaseGeneratedAttribute' for Code First configuration.
The error pops in this code from DataContext.cs
private void SyncObjectsStatePreCommit()
{
    foreach (var dbEntityEntry in ChangeTracker.Entries())
    {
        dbEntityEntry.State = StateHelper.ConvertState(((IObjectState)dbEntityEntry.Entity).ObjectState);
    }
}
I am using a Code First approach and added the needed line in my Mapping to make sure it was ok:
this.Property(t => t.Id).HasColumnName("Id").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
After a lot of investigation, I found that despite setting the ObjecState to "Unchanged", it looks like it's not added correctly when entities are added to the ChangeTracker.Entries().

I can now see a specific LogServerity added twice. The first one has a State of "Added" while the second one has a state of "Unchanged". This is for the same LogSeverity (same object, same Id).

How can it be added multiple times ? Is there a way to valide the entities before adding them to the ChangeTracker ?

My guess is that the bugs comes up at this line because the framework tries to set the state to "Unchanged" and it "maybe" cause a problem to have 2 identical entities with the same status, no ?

Update: The code runs fine when called from a console app. But when called from a MVC controller, the bug occurs.
Coordinator
May 12, 2015 at 5:16 PM
Sounds like you don't have you DI/IoC configured correctly for you MVC app, the IDataContext and DbContext need to have singleton behavior, with it's lifecycle bound to the lifecycle of the http request, please see https://genericunitofworkandrepositories.codeplex.com/SourceControl/latest#main/Sample/Northwind.Web/App_Start/UnityConfig.cs how we've configured this using Unity's PerRequestlifetimeManager.
 container
                .RegisterType<IDataContextAsync, NorthwindContext>(new PerRequestLifetimeManager())
                .RegisterType<IUnitOfWorkAsync, UnitOfWork>(new PerRequestLifetimeManager())
                .RegisterType<IRepositoryAsync<Customer>, Repository<Customer>>()
                .RegisterType<IRepositoryAsync<Product>, Repository<Product>>()
                .RegisterType<IProductService, ProductService>()
                .RegisterType<ICustomerService, CustomerService>()
                .RegisterType<INorthwindStoredProcedures, NorthwindContext>(new PerRequestLifetimeManager())
                .RegisterType<IStoredProcedureService, StoredProcedureService>();
        }
Marked as answer by lelong37 on 5/12/2015 at 10:16 AM