Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Entity framework 如何使用实体框架核心获取主键值_Entity Framework_Primary Key_Repository Pattern_Entity Framework Core - Fatal编程技术网

Entity framework 如何使用实体框架核心获取主键值

Entity framework 如何使用实体框架核心获取主键值,entity-framework,primary-key,repository-pattern,entity-framework-core,Entity Framework,Primary Key,Repository Pattern,Entity Framework Core,我们目前正在使用下面的方法,该方法依赖于抽象存储库中的IObjectContextAdapter。从我所阅读的内容来看,似乎任何与ObjectContext相关的内容都被从实体框架核心中切掉了。下面的方法是我们唯一依赖于任何与ObjectContext相关的东西的地方 我们想升级到实体框架核心。这是我们唯一的路障。有没有办法通过实体框架核心API获取实体主键的值 // Entity Framework public virtual int GetKey(T entity) { var o

我们目前正在使用下面的方法,该方法依赖于抽象存储库中的IObjectContextAdapter。从我所阅读的内容来看,似乎任何与ObjectContext相关的内容都被从实体框架核心中切掉了。下面的方法是我们唯一依赖于任何与ObjectContext相关的东西的地方

我们想升级到实体框架核心。这是我们唯一的路障。有没有办法通过实体框架核心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);
}
//实体框架
公共虚拟int GetKey(T实体)
{
var oContext=((IObjectContextAdapter)_DbContext).ObjectContext;
var oSet=oContext.CreateObjectSet();
var keyName=oSet.EntitySet.ElementType
.主要成员
.选择(k=>k.Name)
.Single();
return(int)entity.GetType().GetProperty(keyName).GetValue(entity,null);
}

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

// 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);
}
//实体框架核心
公共虚拟int GetKey(T实体)
{
var keyName=Context.Model.FindentialType(typeof(T)).FindPrimaryKey().Properties
.Select(x=>x.Name).Single();
return(int)entity.GetType().GetProperty(keyName).GetValue(entity,null);
}

根据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);
    }

  }
公共静态类扩展{
公共静态IEnumerable FindPrimaryKeyNames(此DbContext DbContext,T实体){
从dbContext.FindPrimaryKeyProperties(实体)中的p返回
选择p.名称;
}
公共静态IEnumerable FindPrimaryKeyValues(此DbContext DbContext,T实体){
从dbContext.FindPrimaryKeyProperties(实体)中的p返回
选择entity.GetPropertyValue(p.Name);
}
静态IReadOnlyList FindPrimaryKeyProperties(此DbContext DbContext,T实体){
返回dbContext.Model.FindentialType(typeof(T)).FindPrimaryKey().Properties;
}
静态对象GetPropertyValue(此T实体,字符串名称){
返回entity.GetType().GetProperty(name).GetValue(entity,null);
}
}
然后可以在类似的情况下使用:

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

至少在EF Core 2.1中,您可以通过以下方式获得密钥:

var entry = dbContext.Entry(entity);
object[] keyParts = entry.Metadata.FindPrimaryKey()
             .Properties
             .Select(p => entry.Property(p.Name).CurrentValue)
             .ToArray();
这允许您获取作为阴影属性创建的密钥。

我不知道call
属性(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];
}
私有静态只读ConcurrentDictionary键属性ByEntityType=new ConcurrentDictionary();
公共对象[]KeyOf(tenty实体),其中tenty:class
{
Guard.ArgumentNotNull(实体,名称(实体));
var entry=_dbContext.entry(实体);
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();
返回关键部件;
}
公共TKey KeyOf(TEntity实体),其中TEntity:class
{
var keyParts=KeyOf(实体);
如果(keyParts.Length>1)
{
抛出新的InvalidOperationException($“键是复合的,具有{keyParts.Length}”部分。”);
}
返回(TKey)键部件[0];
}

谢谢您的回答。看起来应该能用。我现在不在那个项目上,但我希望在不久的将来能回到这个项目上。我会尽快试用。EF7中是否添加了Context.Model?我正在EF6环境中尝试更改,但由于该属性不存在而中断。是的,这是EntityFrameworkCore v1.1.2中的EF7(Core)属性FindentialType()的签名只接受实体类型名称的字符串。。。Context.Model.FindEntityType(typeof(T).Name).FindPrimaryKey()…似乎与Core 2.1冲突。现在只返回空值。请注意PK是一个影子属性的可能性。
var entry=\u dbContext.entry(entity);entry.Metadata.FindPrimaryKey().Properties.Select(p=>entry.Property(p.Name).CurrentValue)