2

Since upgrading to .Net Core 3.1, one of my entities throws an error if I try to update it with the error 'cannot update identity column in Entity Framework Core'. This happens in the attached or the detached state.

Here is my fluent config

modelBuilder.Entity<OrderStatus>(b =>
            {
                b.ToTable("OrderStatus");
                b.HasKey(e => e.OrderStatusId);
                b.HasKey(e => new { e.CompanyId, e.OrderId }); //CompositeKey
                b.Property(e => e.OrderStatusId).UseIdentityColumn();
            });

I fetch the entity and update a value (not the OrderStatusId) and call save and thats when it blows up.

var orderStatus = _context.OrderStatus.FirstOrDefault();
orderStatus.Total = 500;
_context.Entry(OrderStatus).State = EntityState.Modified;
await _context.SaveChangesAsync();

I came across this old thread cannot update identity column in Entity Framework Core which mentions a 'fix' of adding

b.Property(e => e.OrderStatusId).Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Ignore);

This indeed does work, but I have no idea why this would be needed. This is the only Table in my application that seems to want this.

FYI, I was previous running on EF core 3.0 and tried upgrading to 3.1.3 but this makes no difference.

Should I be adding this to all of my fluent definitions now?

Suggestions appreciated!

Raj
  • 897
  • 1
  • 15
  • 28

1 Answers1

2

This indeed does work, but I have no idea why this would be needed. This is the only Table in my application that seems to want this.

Should I be adding this to all of my fluent definitions now?

This is needed only for identity columns which are not the primary key (PK) of the table (or Key in EF Core).

Which should be rare - this is why you have issue only with that table.

But do you really need a composite PK (and what's the purpose of the identity column then)? Note that as for any fluent calls, the last HasKey (EF Core fluent API for defining the PK) wins, i.e. here

b.HasKey(e => e.OrderStatusId);
b.HasKey(e => new { e.CompanyId, e.OrderId }); //CompositeKey

the line

b.HasKey(e => e.OrderStatusId);

has no effect, thus by default is eligible for updating. But then why it is here? May be the intention was to have identity PK and composite alternate key? In other words, if the config was

b.HasKey(e => e.OrderStatusId);
b.HasAlternateKey(e => new { e.CompanyId, e.OrderId }); //CompositeKey

then you won't have such issue and won't need to configure AfterSaveBehavior.

And if you really want a composite PK, then remove the misleading

b.HasKey(e => e.OrderStatusId);

line and use the SetAfterSaveBehavior solution.

Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • OK that makes a lot of sense. I believe I do need a composite key in my situation. (there could be an Order with multiple CompanyId's so a each order would generally have a few rows). When I try your change, it does indeed work BUT OrderID gets set as a FK but CompanyID is just set to not null. (The constrains does have a constrain with OrderID_CompanyID though). Is this expected behaviour of a composite key? – Raj Apr 30 '20 at 02:58
  • 1
    Alternate keys in databases are called unique keys. I don't expect FK relationship changes, may be there is something in your model which requires explicitly mapping `CompanyID` as FK. I can't tell exact w/o seeing the whole model. But that wasn't the main point, just the line `b.HasKey(e => e.OrderStatusId);` was suspicious. – Ivan Stoev Apr 30 '20 at 05:28