Attualmente utilizziamo il metodo seguente che dipende da IObjectContextAdapter in un repository astratto. Da quello che sto leggendo, sembra che qualsiasi cosa relativa a ObjectContext sia stata tagliata da Entity Framework Core. Il metodo seguente è l'unico posto in cui dipendiamo da qualsiasi cosa relativa a ObjectContext.
Vorremmo eseguire l'aggiornamento a Entity Framework Core. Questo è il nostro unico blocco stradale. C'è un modo per ottenere il valore della chiave primaria di un'entità con gli apis di Entity Framework Core?
// 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);
}
Ho anche affrontato problemi simili e ho trovato la seguente soluzione
// 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);
}
Almeno in EF Core 2.1 puoi ottenere la chiave in questo modo:
var entry = dbContext.Entry(entity);
object[] keyParts = entry.Metadata.FindPrimaryKey()
.Properties
.Select(p => entry.Property(p.Name).CurrentValue)
.ToArray();
Ciò consente di ottenere la chiave creata come proprietà shadow .
Non so quanto performante sia la Property(p.Name).CurrentValue
Call Property(p.Name).CurrentValue
, tuttavia è ancora possibile memorizzare nella cache i nomi delle proprietà della chiave:
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];
}