Entity Framework Core Code First changing added entities values before save causes identity insert error

.net-core asp.net-core c# ef-code-first entity-framework-core

Question

I got a problem with setting values before saving an added entity. When I don't change the entities values it saves without a problem.

The error I get is this:

SqlException: Cannot insert explicit value for identity column in table 'TableName' when IDENTITY_INSERT is set to OFF.

I am using .net Core 2.1 and my nuget packages are all up to date.

The code below works fine in Entity Framework for the .NET Framework

public override int SaveChanges()
{
    try
    {
        int userId = currentUser.UserId;
        IEnumerable<EntityEntry> addedEntities = ChangeTracker.Entries()
                      .Where(e => e.State == EntityState.Added && e.CurrentValues.ToObject() is ModelBase)
                      .Select(e => e);

        foreach (var e in addedEntities)
        {
            var clE = e.CurrentValues.ToObject() as ModelBase;

            if (clE != null)
            {
                clE.CreatedOn = DateTime.Now;
                clE.CreatedBy = userId;
            }

            // When I delete this line, it works without a problem
            // but it doesn't set the values obviously
            e.CurrentValues.SetValues(clE);
        }

        return base.SaveChanges();
    }
    catch (Exception dbEx)
    {
        Exception raise = dbEx;
        throw raise;
    }
}

Any idea what I am doing wrong?

Thanks Chris

1
1
7/31/2018 1:47:28 PM

Accepted Answer

The documentation of ToObject method states:

Creates an instance of the entity type and sets all its properties using the values from this object.

In other words, the method creates a new entity instance and populates it with the current values of the tracked entity.

Note that at the time you add entity to the context, EF generates temporary values for the identity PK property, so ToObject copies that value as well.

Then SetValues copies back all properties of the passed object, including the PK, but now the PK value is marked as persistent (the same will happen if you set explicitly the PK value to some value different than the default 0).

The net effect of all this is that EF will try to insert explicit value into PK key, which normally is disabled (needs special enabling), hence the exception you are getting.

The solution is to not use ToObject / SetValues, but modify the actual tracked entity, which is accessible through Entity property:

var addedEntities = ChangeTracker.Entries()
    .Where(e => e.State == EntityState.Added)
    .Select(e => e.Entity)
    .OfType<ModelBase>();

foreach (var e in addedEntities)
{
    // Here you modify the actual entity instance, so the values
    // you set will be considered by the base.SaveChanges() call
    e.CreatedOn = DateTime.Now;
    e.CreatedBy = userId;
}
0
8/4/2018 7:52:53 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow