EF 6 calls INSERT instead of UPDATE

.net c# entity-framework entity-framework-6 sql-server

Question

This could be a duplicate question but a lot of searching for the words in the title only got me a lot of unrelated results.

I have an entity that's roughly set up like this:

public abstract class A
{
    public GUID AId { get; set; }

    public string SomeProperty { get; set; }
}

public class B : A
{
    public string SomeOtherProperty { get; set; }
}

The context has public DbSet<B> BInstances { get; set; } for B objects. In OnModelCreating, the mapping has A set to ignored and B is mapped to a table called TableB.

The AId field is not auto-generated (not an identity field) but it's set to be primary key, both in the database and in the mapping. In the database, the field is defined as a non-null uniqueidentifier with no default.

At runtime, I'm loading an instance of B using its key (_token is just a CancellationToken):

var b = await (dbCtx.BInstances.FirstOrDefaultAsync(e => e.AId), _token));

Then, a property of b is set and I try to save it back to database:

b.SomeOtherProperty = "some new text";
await (dbCtx.SaveChangesAsync(_token));

At this point, I'm getting a Violation of PRIMARY KEY constraint error from the database, stating that the value of AId cannot be inserted because it'd be a duplicate. Of course, the ID is already in the database, I loaded the entity from there, using the ID. For some reason, EF generates an INSERT statement, not an UPDATE and I don't understand why.

When I check dbCtx.Entry(b).State, it's already set to EntityState.Modified. I'm at a loss - can someone point out what I'm doing wrong? I never had issues with updating entities before but I haven't used EF with GUID primary keys (usually I use long primary keys).

I'm using EF 6 and .NET Framework 4.7.1.

1
1
6/26/2018 4:02:04 AM

Accepted Answer

Thank you all for the suggestions - this turned out to be a mapping problem that I caused.

In my OnModelCreating() call, I called MapInheritedProperties() on a type that didn't inherit from a base class (other than object, of course) - this seems to have triggered a problem. Other entities that do share a base class worked fine with the mapping call.

I also called ToTable() directly against the entity class - this broke my table mapping for reasons I do not understand. Once I moved that call inside Map(), it started working as expected.

So I went from this:

entity.ToTable("tablename");

to this:

entity.Map(m => m.ToTable("tablename"));

to solve the problem.

Hopefully this will be useful for future readers.

2
7/12/2018 4:17:03 PM

Popular Answer

try this

b.SomeOtherProperty = "some new text";
dbCtx.BInstances.AddOrUpdate(b);
await (dbCtx.SaveChangesAsync(_token));

AddorUpdate will update your b instance if it is already added.



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