8

I am trying to get primary key information for each entry that I am inserting, updating, or deleting in an EF5 application. I use code similar to this:

//Get collection of each insert, update, or delete made on the entity. 
IEnumerable<DbEntityEntry> changedEntries = this.ChangeTracker.Entries()
    .Where(e => e.State == EntityState.Added
        || e.State == EntityState.Modified
        || e.State == EntityState.Deleted);

foreach (DbEntityEntry entry in changedEntries)
{
    //Get primary key collection
    EntityKey key = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager
        .GetObjectStateEntry(entry.Entity).EntityKey;

    string keyName;
    //Get name of first key. Make sure a collection was returned.
    if (key.EntityKeyValues != null)
        keyName = key.EntityKeyValues[0].Key;
    else
        keyName = "(NotFound)";
}

The problem with this code, however, is that it is not working when a new record is being inserted into the database. When the entry's state is EntityState.Added, the key.EntityKeyValues has a null value (this code set the value of keyName to "(NotFound)".

Is there a way to get the column name for the primary key when a record is being inserted?

Pizzor2000
  • 379
  • 3
  • 19
  • Why get the key name from objects again and again? You should get it from the metadata: http://stackoverflow.com/q/7253943/861716. – Gert Arnold Sep 11 '14 at 07:43

2 Answers2

14

I figured out a way to do it, combining my original code with code from the link Gert posted:

//Get collection of each insert, update, or delete made on the entity. 
IEnumerable<DbEntityEntry> changedEntries = this.ChangeTracker.Entries()
    .Where(e => e.State == EntityState.Added
        || e.State == EntityState.Modified
        || e.State == EntityState.Deleted);

foreach (DbEntityEntry entry in changedEntries)
{
    EntitySetBase setBase = ObjectContext.ObjectStateManager
        .GetObjectStateEntry(entry.Entity).EntitySet;

    string[] keyNames = setBase.ElementType.KeyMembers.Select(k => k.Name).ToArray();
    string keyName;
    if (keyNames != null)
        keyName = keyNames.FirstOrDefault();
    else
        keyName = "(NotFound)";
}

So far, it seems to be working, even when I add a new record.

Pizzor2000
  • 379
  • 3
  • 19
  • 3
    If you need the value: int keyOrdinal = entry.CurrentValues.GetOrdinal(keyName); string keyVal = entry.CurrentValues.GetValue(keyOrdinal); – MJK Feb 26 '16 at 15:03
  • 3
    The value can also be retrieved with `var keyVal = entry.CurrentValues[keyName];` – Tim Jan 13 '17 at 10:52
  • Note, you have to use `entry.OriginalValues[keyName]` when deleting. – Gabe Oct 21 '21 at 19:26
0

After SaveChanges(), your primary key is in place. You could keep changedList before SaveChanges() and then save change log after SaveChanges().

Ref http://webmisterradixlecti.blogspot.co.nz/2013/04/get-primary-key-on-insert-using-entity.html

Kan Lu
  • 1