如何获取ObjectSet 的实体密钥名称?

我在我的通用存储库中创建了一个通用的ObjectSet

我想得到的是ObjectSet的EntityKey的name ,以便我可以在DataContext.GetObjectByKey使用它。

我已经四处搜索并深入挖掘,但我似乎无法在ObjectSet类中的任何位置找到此值。

我刚才看到了一个很好的方法来做到这一点并没有找到一个。 我通常最终在某处和其中构建一个GetEntityByKey扩展方法,连接字符串以构建TryGetObjectByKey调用的实体密钥。 构建实体键的一般想法是这样的:

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

你也许可以做类似的事情。 为简单起见,此示例假定每个EntityKey使用一个字段 – 对于多个值键,您需要使用ObjectSet.ElementType.KeyMembers执行稍微复杂的操作,并将所有键传递到EntityKey构造函数中。

通用:

 public class GenericoRepositorio : IGenericoRepositorio where T : class { protected readonly ObjectSet ObjetoSet; protected readonly ModeloContainer Contexto; public GenericoRepositorio(ModeloContainer contexto) { Contexto = contexto; ObjetoSet = Contexto.CreateObjectSet(); } public T Carregar(int id) { object objeto; Contexto.TryGetObjectByKey(GetEntityKey(ObjetoSet, id), out objeto); return (T)objeto; } private static EntityKey GetEntityKey(ObjectSet 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; } } 

查看我关于获取EntitySetName的post 。 对于我的存储库,我创建了一个属性,该属性获取特定类名的实体集名称,以完成您要执行的操作。

这应该为您提供ObjectSet的所有通用参数(类型):

 objectSet.GetType().GetGenericArguments().First() 

我很难尝试做几乎相同的事情,在类型未知时在运行时获取主键名称和值。 我只是试图实现删除审计方案,我发现的每个解决方案都涉及多余的代码,我真的不明白。 DbContext不提供EntityKey,这也令人困惑和恼人。 最后5行可以为您节省5小时和1年的秃头。 我没有尝试插入,所以如果你这样做,你需要仔细检查这些值,因为它们可能是0或null。

 foreach(var entry in ChangeTracker.Entries()) { ... 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; 

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

var objSet = objContext.CreateObjectSet();

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 entry = this.context.Entry(this.dbset.Find(entityKey.EntityKeyValues.FirstOrDefault().Value)); entry.CurrentValues.SetValues(entityToUpdate); } } this.context.SaveChanges(); 

用EF 6测试。

它将为给定的DbEntityEntry的每个主键值返回一个对象数组。

他们可能是边缘情况,这不起作用 – 但对我的简单需求很有效。

希望这有助于其他人。

 object[] GetPrimaryKeyValue(DbEntityEntry entry) { List key = new List(); 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(); }