首先在代码中获取任意实体的主键值

时间:2011-08-31 09:31:52

标签: c# entity-framework-4.1

有这样的方法吗?

object GetPrimaryKeyValue(DbEntityEntry entry);

或者应该如何实施?

4 个答案:

答案 0 :(得分:30)

您需要将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属性。

答案 1 :(得分:0)

我也希望找到实体的主键。我在我的存储库中使用Generics,所以我不知道实体直到运行时。到目前为止,我发现这样做的唯一方法是使用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);

这只是全班的一部分,但希望能够展示我正在使用的解决方案。

答案 2 :(得分:0)

您不需要附加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
      }



    }
  }

答案 3 :(得分:0)

我知道这有点旧,但我刚看到这个。

这是我是怎么做的(假设 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;
        }
    }
}