How to get the Primary Key(s) in Entity Framework 4.1, i.e. using DbContext

后端 未结 5 1889
逝去的感伤
逝去的感伤 2020-12-29 08:52

The answers I\'m seeing here are for ObjectContext. Is there a property to determine an entity\'s primary key names when using DbContext?

Ah.. one of those times tha

相关标签:
5条回答
  • 2020-12-29 09:40

    The solution proposed by Ladislav Mrnka won't work for derived entities as You can't create an object set for a derived type. You'll see this error :

    ArgumentException: There are no EntitySets defined for the specified entity type ... If ... is a derived type, use the base type instead. Parameter name: TEntity

    Here is my solution avoiding creating an object set :

    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();
    }
    
    0 讨论(0)
  • 2020-12-29 09:42

    You cannot use DbContext for that - DbContext API is just dumb wrapper with only most needed functionality. For everything more complex you must convert DbContext back to ObjectContext and use it. Try something like this:

    Extract key names:

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

    Here's a method that will extract the key values of an entity:

    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));
    }
    
    0 讨论(0)
  • 2020-12-29 09:47

    you can get to ObjectContext because DbContext mostly wraps ObjectContext...

    see
    http://msdn.microsoft.com/en-us/library/gg696590%28v=vs.103%29.aspx
    http://msdn.microsoft.com/en-us/library/system.data.entity.dbcontext%28v=vs.103%29.aspx
    http://msdn.microsoft.com/en-us/library/dd283139.aspx

    0 讨论(0)
  • 2020-12-29 09:51

    Here is what I did to make sure that I got the key. It is essentially the same as @Agus Syahputra 's answer with one important difference. I've added the entire answer below.

    Note: I've tested this only on EF6 and I'm not sure if this works with earlier versions of 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;
    
    0 讨论(0)
  • 2020-12-29 09:54

    You could find primary key value from EntityKey class (http://msdn.microsoft.com/en-us/library/system.data.entitykey.aspx).

    and you could find EntityKey object from DbContext like so :

    ObjectContext context = ((IObjectContextAdapter)dbContext).ObjectContext;
    EntityKey key = context.ObjectStateManager.GetObjectStateEntry(model).EntityKey;
    
    0 讨论(0)
提交回复
热议问题