【问题标题】:How to get primary key value with Entity Framework Core如何使用 Entity Framework Core 获取主键值
【发布时间】:2015-08-21 17:24:04
【问题描述】:

我们目前正在使用下面的方法,它依赖于抽象存储库中的 IObjectContextAdapter。从我正在阅读的内容来看,与 ObjectContext 相关的任何内容似乎都已从 Entity Framework Core 中删除。下面的方法是我们唯一依赖与 ObjectContext 相关的任何东西的地方。

我们想升级到 Entity Framework Core。这是我们唯一的路障。有没有办法通过Entity Framework Core api获取实体的主键值?

// 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);
}

【问题讨论】:

  • var entry = _dbContext.Entry(entity); entry.Metadata.FindPrimaryKey().Properties.Select(p =&gt; entry.Property(p.Name).CurrentValue);

标签: entity-framework primary-key repository-pattern entity-framework-core


【解决方案1】:

我也遇到了类似的问题,找到了以下解决方案

// 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);
}

【讨论】:

  • 感谢您的回答。看起来它应该工作。我目前不在那个项目上,但我希望在不久的将来会回来。我会尽快尝试。
  • 是EF7中添加的Context.Model吗?我正在尝试在 EF6 环境中进行更改,但由于该属性不存在而中断。
  • 是的,这是 EF7(核心)属性
  • 在 EntityFrameworkCore v1.1.2 中,FindEntityType() 的签名只需要一个字符串作为实体类型名称。 ... Context.Model.FindEntityType(typeof(T).Name).FindPrimaryKey()...
  • 似乎被 Core 2.1 破坏了。现在只返回空值。
【解决方案2】:

至少在 EF Core 2.1 中,您可以通过这种方式获取密钥:

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

这允许您获取创建为 shadow 属性的密钥。

我不知道调用Property(p.Name).CurrentValue 的性能如何,但是仍然可以缓存键的属性名称:

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];
}

【讨论】:

    【解决方案3】:

    根据 YuriyP 的回答,您还可以获得复合键信息:

     public static class Extensions {
    
        public static IEnumerable<string> FindPrimaryKeyNames<T>(this DbContext dbContext, T entity) {
          return from p in dbContext.FindPrimaryKeyProperties(entity) 
                 select p.Name;
        }
    
        public static IEnumerable<object> FindPrimaryKeyValues<T>(this DbContext dbContext, T entity) {
          return from p in dbContext.FindPrimaryKeyProperties(entity) 
                 select entity.GetPropertyValue(p.Name);
        }
    
        static IReadOnlyList<IProperty> FindPrimaryKeyProperties<T>(this DbContext dbContext, T entity) {
          return dbContext.Model.FindEntityType(typeof(T)).FindPrimaryKey().Properties;
        }
    
        static object GetPropertyValue<T>(this T entity, string name) {
          return entity.GetType().GetProperty(name).GetValue(entity, null);
        }
    
      }
    

    然后可以像这样使用:

    var keyValues = context.FindPrimaryKeyValues(entity);    
    var existingEntity = context.Set<TEntity>().Find(keyValues);
    

    【讨论】:

    • 当心 PK 是影子属性的可能性。
    猜你喜欢
    • 2022-09-27
    • 1970-01-01
    • 1970-01-01
    • 2019-02-13
    • 2018-09-03
    • 1970-01-01
    • 2018-07-21
    • 2016-07-09
    • 1970-01-01
    相关资源
    最近更新 更多