How to get ObjectSet's entity key name?

后端 未结 7 1367
悲哀的现实
悲哀的现实 2020-12-29 00:08

I\'ve created a generic ObjectSet in my generic repository.

What I would like to get is the name of the EntityKey of ObjectS

相关标签:
7条回答
  • 2020-12-29 00:22

    I looked a while ago for a nice way to do this and failed to find one. I generally end up building a GetEntityByKey extension method somewhere and within that, contatenating strings to build Entity Keys for TryGetObjectByKey calls. The general idea for building the entity key goes something like this:

    internal class Program
    {
        private static void Main(string[] args)
        {
            var dc = new AdventureWorksLT2008Entities();
            object c;
            dc.TryGetObjectByKey(GetEntityKey(dc.Customers, 23), out c);
            var customer = c as Customer;
            Console.WriteLine(customer.EmailAddress);
        }
    
        private static EntityKey GetEntityKey<T>(ObjectSet<T> objectSet, object keyValue) where T : class
        {
            var entitySetName = objectSet.Context.DefaultContainerName + "." + objectSet.EntitySet.Name;
            var keyPropertyName = objectSet.EntitySet.ElementType.KeyMembers[0].ToString();
            var entityKey = new EntityKey(entitySetName, new[] {new EntityKeyMember(keyPropertyName, keyValue)});
            return entityKey;
        }
    }
    

    You may be able to do something similar. This example assumes a single field per EntityKey for simplicity - for multiple value keys you would need to do something slightly more sophisticated with ObjectSet<T>.ElementType.KeyMembers and pass all your keys into the EntityKey constructor.

    0 讨论(0)
  • 2020-12-29 00:33

    Generic:

    public class GenericoRepositorio<T> : IGenericoRepositorio<T> where T : class
    {
        protected readonly ObjectSet<T> ObjetoSet;
        protected readonly ModeloContainer Contexto;
    
        public GenericoRepositorio(ModeloContainer contexto)
        {
            Contexto = contexto;
            ObjetoSet = Contexto.CreateObjectSet<T>();
        }
    
        public T Carregar(int id)
        {
            object objeto;
            Contexto.TryGetObjectByKey(GetEntityKey(ObjetoSet, id), out objeto);
            return (T)objeto;
        }
    
        private static EntityKey GetEntityKey<T>(ObjectSet<T> objectSet, object keyValue) where T : class
        {
            var entitySetName = objectSet.Context.DefaultContainerName + "." + objectSet.EntitySet.Name;
            var keyPropertyName = objectSet.EntitySet.ElementType.KeyMembers[0].ToString();
            var entityKey = new EntityKey(entitySetName, new[] { new EntityKeyMember(keyPropertyName, keyValue) });
            return entityKey;
        }
    }
    
    0 讨论(0)
  • 2020-12-29 00:33

    I had a tough time trying to do almost the same thing, getting the primary key name and value at runtime when the type is unknown. I was just get trying to implement an auditing scheme for deletes, and every solution i find involves superfluous code that I dont really understand. The EntityKey is not available from a DbContext, which is also confusing and annoying. The last 5 lines may save you 5 hours and 1 yr of baldness. I am not attempting this for Inserts, so if you do, you need to inspect those values carefully as they may be 0 or null.

    foreach(var entry in ChangeTracker.Entries<IAuditable>())
    {
    ...
    
    case EntityState.Deleted:
    
    var oc = ((IObjectContextAdapter)this).ObjectContext;  //this is a DbContext
    EntityKey ek = oc.ObjectStateManager.GetObjectStateEntry(entry.Entity).EntityKey;
    var tablename = ek.EntitySetName;
    var primaryKeyField = ek.EntityKeyValues[0].Key;     //assumes only 1 primary key
    var primaryKeyValue = ek.EntityKeyValues[0].Value;
    
    0 讨论(0)
  • 2020-12-29 00:36

    var objContext = ((IObjectContextAdapter)this.context).ObjectContext;

    var objSet = objContext.CreateObjectSet<T>();

    var entityKey = objContext.CreateEntityKey(objSet.EntitySet.Name, entityToUpdate);

    Object foundEntity;

    var exits = objContext.TryGetObjectByKey(entityKey, out foundEntity);

    if (exits && this.dbset.Local != null && this.dbset.Local.Contains(foundEntity) &&this.dbset.Local.Any())                    
    {
      if (entityKey.EntityKeyValues != null && entityKey.EntityKeyValues.Any())                       
      {       
        DbEntityEntry<T> entry = this.context.Entry(this.dbset.Find(entityKey.EntityKeyValues.FirstOrDefault().Value));
                            entry.CurrentValues.SetValues(entityToUpdate);
       }
    }
    
    this.context.SaveChanges();
    
    0 讨论(0)
  • 2020-12-29 00:46

    This should give you all the generic arguments (the types) for the ObjectSet:

    objectSet.GetType().GetGenericArguments().First()
    
    0 讨论(0)
  • 2020-12-29 00:47

    Tested with EF 6.

    It will return an array of objects for each primary key value for the given DbEntityEntry.

    Their maybe edge cases where this does not work - but for my simple needs works great.

    Hope this helps someone else.

    object[] GetPrimaryKeyValue(DbEntityEntry entry)
    {
        List<object> key = new List<object>();
    
        var objectStateEntry = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager.GetObjectStateEntry(entry.Entity);
        if (objectStateEntry.EntityKey.EntityKeyValues != null && objectStateEntry.EntityKey.EntityKeyValues.Length==1)
        {
            key.Add(objectStateEntry.EntityKey.EntityKeyValues[0].Value);
        }
        else
        {
            if (objectStateEntry.EntitySet.ElementType.KeyMembers.Any())
            {
                foreach (var keyMember in objectStateEntry.EntitySet.ElementType.KeyMembers)
                {
                    if (entry.CurrentValues.PropertyNames.Contains(keyMember.Name))
                    {
                        var memberValue = entry.CurrentValues[keyMember.Name];
                        if (memberValue != null)
                        {
                            key.Add(memberValue);
                        }
                    }
                }
            }
        }
        return key.ToArray();
    }
    
    0 讨论(0)
提交回复
热议问题