【问题标题】:How to get the Primary Key(s) in Entity Framework 4.1, i.e. using DbContext如何在 Entity Framework 4.1 中获取主键,即使用 DbContext
【发布时间】:2011-08-02 02:47:24
【问题描述】:

我在这里看到的答案是针对 ObjectContext。使用 DbContext 时是否有确定实体主键名称的属性?

啊.. 我希望 Entity Framework 是开源的时代之一!我可以从 .Find 方法中收集到这个主键名称信息 :-)

【问题讨论】:

标签: entity-framework entity-framework-4.1


【解决方案1】:

您不能为此使用DbContext - DbContext API 只是愚蠢的包装器,只有最需要的功能。对于更复杂的一切,您必须将DbContext 转换回ObjectContext 并使用它。试试这样的:

提取键名

public static string[] GetEntityKeyNames<TEntity>(this DbContext context) where TEntity : class
{
  if (context == null)
    throw new ArgumentNullException("context");

  var set = ((IObjectContextAdapter)context).ObjectContext.CreateObjectSet<TEntity>();
  var entitySet = set.EntitySet;
  return entitySet.ElementType.KeyMembers.Select(k => k.Name).ToArray();
}

这是一个提取实体的键值的方法:

public static IEnumerable<object> GetEntityKeys<TEntity>(this DbContext context, TEntity entity)
  where TEntity : class
{
  if (context == null)
    throw new NullReferenceException("context");

  var type = typeof(TEntity);

  var set = ((IObjectContextAdapter)context).ObjectContext.CreateObjectSet<TEntity>();
  var entitySet = set.EntitySet;
  var keys = entitySet.ElementType.KeyMembers;
  var props = keys.Select(k => type.GetProperty(k.Name));
  return props.Select(p => p.GetValue(entity));
}

【讨论】:

  • 如果 TEntity 是派生类,我认为这不会起作用。没有 CreateObjectSet 有没有办法做到这一点?
  • 万一其他人尝试此操作(EF 6)并收到一条消息:类型“TEntity”必须是引用类型才能将其用作参数...它需要where TEntity : class约束。 CreateObjectSet 签名和定义:msdn.microsoft.com/en-us/library/dn236948%28v=vs.113%29.aspx
  • 我们应该处置创建的 ObjectSet 吗?
  • @Guillaume,不,这不是IDisposable
【解决方案2】:

solution proposed by Ladislav Mrnka 不适用于作为You can't create an object set for a derived type 的派生实体。你会看到这个错误:

ArgumentException:没有为指定的实体集定义 实体类型 ... 如果 ... 是派生类型,请使用 而是基本类型。参数名称:TEntity

这是我避免创建对象集的解决方案:

public string[] GetEntityKeyNames<TEntity>(DbContext context)
{
    if (context == null)
    {
        throw new ArgumentNullException("context");
    }
    var objectContext = ((IObjectContextAdapter)Context).ObjectContext;
    //We must use the namespace of the context and the type name of the entity
    string entityTypeName = context.GetType().Namespace + '.' + typeof(TEntity).Name;
    var entityType = objectContext.MetadataWorkspace.GetItem<EntityType>(entityTypeName, DataSpace.CSpace);
    return entityType.KeyProperties.Select(k => k.Name).ToArray();
}

【讨论】:

    【解决方案3】:

    【讨论】:

    • 我已经知道 ((db as IObjectContextAdapter).ObjectContext),我正在尝试找出如何获取实体的主键名称
    • 这是旧方法,但它会命中数据库stackoverflow.com/questions/2958921/…
    【解决方案4】:

    您可以从 EntityKey 类 (http://msdn.microsoft.com/en-us/library/system.data.entitykey.aspx) 中找到主键值。

    你可以像这样从 DbContext 中找到 EntityKey 对象:

    ObjectContext context = ((IObjectContextAdapter)dbContext).ObjectContext;
    EntityKey key = context.ObjectStateManager.GetObjectStateEntry(model).EntityKey;
    

    【讨论】:

    • @agussyahpurta 这仅在对象状态管理器具有模型对象的状态时才有效,否则它将崩溃
    【解决方案5】:

    这是我为确保拿到钥匙所做的工作。它与@Agus Syahputra 的答案基本相同,但有一个重要区别。我在下面添加了整个答案。

    注意:我仅在 EF6 上对此进行了测试,我不确定这是否适用于早期版本的 EF。

    //I'm currently inside savechanges of my dbcontext
    //if you're typing this code outside your dbcontext, replace this with your dbcontext    
    var objectStateEntry = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager.GetObjectStateEntry(entry.Entity);
        string keyName = objectStateEntry.EntityKey.EntityKeyValues[0].Key;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多