开发者

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;
        }
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜