entity framework4:如何查找主键?

我正在尝试使用EF4创建一个通用方法来查找对象的主键。

public string GetPrimaryKey() { ... } 

为了提供更多信息,我正在使用Tekpub StarterKit,下面是我试图启动和运行的课程

 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Data.Objects; using System.Data.Objects.ELinq; using System.Data.Linq; using Web.Infrastructure.Storage.EF4; namespace Web.Infrastructure.Storage { public class EFSession:ISession { PuzzleEntities _db;//This is an ObjectContext public EFSession() { _db = new PuzzleEntities(); } public void CommitChanges() { _db.SaveChanges(); } ///  /// Gets the table provided by the type T and returns for querying ///  private ObjectSet GetObjectSet() where T:class { return _db.CreateObjectSet(); } private T GetByPrimaryKey() where T: class { ..... } public void Delete(System.Linq.Expressions.Expression<Func> expression) where T: class{ foreach (T item in All().Where(expression)) { GetObjectSet().DeleteObject(item); } } public void Delete(T item) where T : class { GetObjectSet().DeleteObject(item); } public void DeleteAll() where T : class { foreach(T item in All()) { GetObjectSet().DeleteObject(item); } } public void Dispose() { _db.Dispose(); } public T Single(System.Linq.Expressions.Expression<Func> expression) where T:class { return GetObjectSet().SingleOrDefault(expression); } public IQueryable All() where T : class { return GetObjectSet().AsQueryable(); } public void Add(T item) where T : class { GetObjectSet().AddObject(item); } public void Add(IEnumerable items) where T : class { foreach (T item in items) { GetObjectSet().AddObject(item); } } public void Update(T item) where T : class { //nothing needed here } } } 

所以我终于能够找到如何使这个工作。 我希望我没有丢失我昨晚读到的博客的链接,因为我没有写代码。

 public T GetByPrimaryKey(int id) where T : class { return (T)_db.GetObjectByKey(new EntityKey(_db.DefaultContainerName + "." + this.GetEntityName(), GetPrimaryKeyInfo().Name, id)); } string GetEntityName() { string name = typeof(T).Name; if (name.ToLower() == "person") return "People"; else if (name.Substring(name.Length - 1, 1).ToLower() == "y") return name.Remove(name.Length - 1, 1) + "ies"; else if (name.Substring(name.Length - 1, 1).ToLower() == "s") return name + "es"; else return name + "s"; } private PropertyInfo GetPrimaryKeyInfo() { PropertyInfo[] properties = typeof(T).GetProperties(); foreach (PropertyInfo pI in properties) { System.Object[] attributes = pI.GetCustomAttributes(true); foreach (object attribute in attributes) { if (attribute is EdmScalarPropertyAttribute) { if ((attribute as EdmScalarPropertyAttribute).EntityKeyProperty == true) return pI; } else if (attribute is ColumnAttribute) { if ((attribute as ColumnAttribute).IsPrimaryKey == true) return pI; } } } return null; } 

我希望这有助于其他人。 我只能说,如何做到这一点应该更清楚一些。

每个名为EntityKey EF4实体都有一个属性,它包含一个EntityKeyValues数组(如果是复合键,则为数组)。

您可以直接在您的实体实例上引用它,或者创建一个通用的帮助方法来实现这一点。 如果我可以测试一些示例代码,我会在这里发布。

编辑 :EntityKeyValue是KeyValuePair ,其中key是实体的主键字段, value是关联值。

例如,我有一个名为Company的实体,其主键是字段Symbol

 var firstCompany = (from c in context.Companies select c).FirstOrDefault(); var kvp = firstCompany.EntityKey.EntityKeyValues[0]; // kvp shows {[Symbol, FOO]} 

在我的沙箱中,我注意到当我在代码中创建实体时,此属性为null 。 但是一旦我从数据库中读取实体,它就被正确填充了。 因此,似乎主键的EF4概念只有在它到达数据库时才能发挥作用。 虽然如果您愿意,可以提前明确地设置它。

我假设很多人只是通过查看“entity framework如何找到主键?”来阻止这篇文章。 无论EF版本(像我一样)。 所以我想提一下,使用EF 6.1,您还可以创建扩展方法来获取主键。 以下是示例,完美无缺。

PS:我不是100%肯定,如果那可以使用复合键和复合键。

 using System; using System.Data.Entity; using System.Data.Entity.Core.Metadata.Edm; using System.Data.Entity.Infrastructure; using System.Linq; namespace System.Data.Entity { public static class DbContextExtensions { public static string[] GetKeyNames(this DbContext context) where TEntity : class { return context.GetKeyNames(typeof(TEntity)); } public static string[] GetKeyNames(this DbContext context, Type entityType) { var metadata = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace; // Get the mapping between CLR types and metadata OSpace var objectItemCollection = ((ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace)); // Get metadata for given CLR type var entityMetadata = metadata .GetItems(DataSpace.OSpace) .Single(e => objectItemCollection.GetClrType(e) == entityType); return entityMetadata.KeyProperties.Select(p => p.Name).ToArray(); } } } 

原始来源

这似乎是不必要的长? 我有同样的需求,并使用上面的建议(由SethO和denis_n),我正在使用:

  //get the primary key field name and location for the table var primaryFieldName = entry.EntitySet.ElementType.KeyMembers[0].Name ; int primaryFieldLocation = entry.CurrentValues.GetOrdinal(primaryFieldName); //gets the value pair for the primary key (returns field name + value) var primaryField = entry.EntityKey.EntityKeyValues[primaryFieldLocation]; String primaryFieldValue = primaryField.Value.ToString(); 

希望这可以帮助任何有兴趣的人