先获取代码中任意实体的主键值
Posted
技术标签:
【中文标题】先获取代码中任意实体的主键值【英文标题】:Get the primary key value of an arbitrary entity in code first 【发布时间】:2011-08-31 09:31:51 【问题描述】:有这样的方法吗?
object GetPrimaryKeyValue(DbEntityEntry entry);
或者应该如何实现?
【问题讨论】:
【参考方案1】:您需要将DbContext
转换为IObjectContextAdapter
,这样您就可以访问底层的ObjectContext
,这使您可以访问DbContext
隐藏的一些更高级的功能。
在派生DbContext
的类中,以下方法将起作用。
object GetPrimaryKeyValue(DbEntityEntry entry)
var objectStateEntry = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager.GetObjectStateEntry(entry.Entity);
return objectStateEntry.EntityKey.EntityKeyValues[0].Value;
如果有多个键,则应遍历 EntityKeyValues
属性。
【讨论】:
仅当实体存在于ObjectStateManager
中时才有效。有没有办法获取分离条目的实体键?
我有同样的问题。每当我引用 ObjectStateManager 时,我都会收到此错误。 ObjectStateManager 不包含引用“NAME_OF_ENTITY”类型对象的 ObjectStateEntry
@Shimmy,看看我的回答
@Hemslingo,看看我的回答【参考方案2】:
我也在寻找实体的主键。我在我的存储库中使用泛型,所以直到运行时我才知道实体。到目前为止,我发现这样做的唯一方法是使用 sql 语句。
public abstract class GenericRepository<T> : ApiController,IGenericRepository<T> where T : class
string sqlstr = @"
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE OBJECTPROPERTY(OBJECT_ID(CONSTRAINT_SCHEMA + '.' + CONSTRAINT_NAME), 'IsPrimaryKey') = 1
AND TABLE_NAME = '" + typeof(T).ToString() + "' AND TABLE_SCHEMA = 'dbo'";
private Entities _entities = new Entities();
public virtual IQueryable<T> GetAll()
DbSqlQuery<T> queryTest = _entities.Set<T>().SqlQuery(sqlstr);
这只是完整课程的一部分,但希望能展示我正在使用的解决方案。
【讨论】:
【参考方案3】:您不需要附加的T item
。这可能是冗长的,但它确实有效。
public object[] GetPrimaryKeyValues<T>(DbContext databaseContext, T item)
return ((IObjectContextAdapter)databaseContext).ObjectContext.CreateEntityKey(typeof(T).Name.Pluralize(), item).EntityKeyValues.Select(kv => kv.Value).ToArray();
例如,返回类型适合在Find
中使用。看,键值实际上是一个对象数组。
如果你需要 Pluralize(),这里是:
using System;
using System.Data.Entity.Design.PluralizationServices;
using System.Linq;
using System.Reflection;
namespace Atlas.Core.Kernel.Extensions
public static class Strings
private static PluralizationService pluralizationService = PluralizationService.CreateService(System.Globalization.CultureInfo.CurrentUICulture);
public static string Pluralize(this MemberInfo memberInfo)//types, propertyinfos, ect
return Pluralize(memberInfo.Name.StripEnd());
public static string Pluralize(this string name)
return pluralizationService.Pluralize(name); // remove EF type suffix, if any
【讨论】:
【参考方案4】:我知道这有点旧,但我才看到这个。
这是我是怎么做到的(假设 pk 是 int)
public class Repository<T> : IDisposable, where T: class, new()
private int GetPrimaryKey(T item)
if (item == null)
return -1;
using (var db = new ApplicationContext())
ObjectSet<T> set = (db as IObjectContextAdapter).ObjectContext.CreateObjectSet<T>();
string keyName = set.EntitySet
.ElementType
.KeyMembers
.Select(x => x.Name)
.First();
Type type = typeof(T);
int val = int.Parse(type.GetProperty(keyName).GetValue(item).ToString());
return val;
【讨论】:
以上是关于先获取代码中任意实体的主键值的主要内容,如果未能解决你的问题,请参考以下文章
附加类型实体失败,因为相同类型的另一个实体已经具有相同的主键值。
ASP.NET MVC - 附加类型为“MODELNAME”的实体失败,因为同一类型的另一个实体已经具有相同的主键值