Get the primary key value of an arbitrary entity in code first
Is开发者_运维技巧 there such a method?
object GetPrimaryKeyValue(DbEntityEntry entry);
Or how should it be implemented?
You need to cast your DbContext
to IObjectContextAdapter
so you can access the underlying ObjectContext
which gives you access to some more advanced features hidden by DbContext
.
Inside your class which derives DbContext
the following method will work.
object GetPrimaryKeyValue(DbEntityEntry entry)
{
var objectStateEntry = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager.GetObjectStateEntry(entry.Entity);
return objectStateEntry.EntityKey.EntityKeyValues[0].Value;
}
If there is more than one key then you should iterate over the EntityKeyValues
property.
I am also looking to find the Primary Key of an entity. I am using Generics in my repository so I don't know the Entity until runtime. The only way I have found to do this so far is with a sql statement.
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);
This is just a pratial of the full class but hopefully shows the solution I am using.
You don't need an attached T item
. This may be long winded, but it works.
public object[] GetPrimaryKeyValues<T>(DbContext databaseContext, T item)
{
return ((IObjectContextAdapter)databaseContext).ObjectContext.CreateEntityKey(typeof(T).Name.Pluralize(), item).EntityKeyValues.Select(kv => kv.Value).ToArray();
}
The return type is suitable to use in a Find
, for example. See, the key values is actually an array of objects.
If you need Pluralize(), here it is:
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
}
}
}
I know this is a bit old but I just saw this.
Heres How I did it (assumes pk is 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;
}
}
}
精彩评论