Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get primary key value with Entity Framework Core

We are currently using the method below which depends upon IObjectContextAdapter in an abstract Repository. From what I'm reading, it appears that anything related to ObjectContext is being chopped out of Entity Framework Core. The method below is the only place we depend upon anything related to ObjectContext.

We'd like to upgrade to Entity Framework Core. This is our only road block. Is there a way to get the value of the primary key of an entity with the Entity Framework Core apis?

// Entity Framework public virtual int GetKey(T entity) {     var oContext = ((IObjectContextAdapter)_DbContext).ObjectContext;     var oSet = oContext.CreateObjectSet<T>();     var keyName = oSet.EntitySet.ElementType                                 .KeyMembers                                 .Select(k => k.Name)                                 .Single();      return (int)entity.GetType().GetProperty(keyName).GetValue(entity, null); } 
like image 874
cResults Avatar asked Jun 07 '15 00:06

cResults


People also ask

How do I get identity value in EF core?

EF execute each INSERT command followed by SELECT scope_identity() statement. SCOPE_IDENTITY returns the last identity value inserted into an identity column in the same scope. The above example will execute the following SQL in the database. WHERE @@ROWCOUNT = 1 AND [StudentID] = scope_identity();

What is the EF core convention for primary keys?

EF Core will specify that the primary key column values are generated automatically by the database.

How do I set primary key in Entity Framework?

Configuring a primary key By convention, a property named Id or <type name>Id will be configured as the primary key of an entity. Owned entity types use different rules to define keys. You can configure a single property to be the primary key of an entity as follows: Data Annotations.


2 Answers

I also faced with similar problem and found the following solution

// Entity Framework Core public virtual int GetKey<T>(T entity) {     var keyName = Context.Model.FindEntityType(typeof (T)).FindPrimaryKey().Properties         .Select(x => x.Name).Single();      return (int)entity.GetType().GetProperty(keyName).GetValue(entity, null); } 
like image 198
YuriyP Avatar answered Oct 01 '22 19:10

YuriyP


At least in EF Core 2.1 you can get the key this way:

var entry = dbContext.Entry(entity); object[] keyParts = entry.Metadata.FindPrimaryKey()              .Properties              .Select(p => entry.Property(p.Name).CurrentValue)              .ToArray(); 

This allows you to get the key which is created as a shadow property.

I do not know how performant is the call Property(p.Name).CurrentValue, nevertheless it is still possible to cache the names of properties of the key:

private static readonly ConcurrentDictionary<Type,string[]> KeyPropertiesByEntityType = new ConcurrentDictionary<Type, string[]>();  public object[] KeyOf<TEntity>(TEntity entity) where TEntity : class {     Guard.ArgumentNotNull(entity, nameof(entity));      var entry = _dbContext.Entry(entity);     var keyProperties = KeyPropertiesByEntityType.GetOrAdd(         entity.GetType(),         t => entry.Metadata.FindPrimaryKey().Properties.Select(property => property.Name).ToArray());      var keyParts = keyProperties         .Select(propertyName => entry.Property(propertyName).CurrentValue)         .ToArray();      return keyParts; }  public TKey KeyOf<TEntity, TKey>(TEntity entity) where TEntity : class {     var keyParts = KeyOf(entity);     if (keyParts.Length > 1)     {         throw new InvalidOperationException($"Key is composite and has '{keyParts.Length}' parts.");     }      return (TKey) keyParts[0]; } 
like image 26
Pavel Voronin Avatar answered Oct 01 '22 21:10

Pavel Voronin