【问题标题】:Get the primary key value of an arbitrary entity in code first先获取代码中任意实体的主键值
【发布时间】:2011-08-31 09:31:51
【问题描述】:

有这样的方法吗?

object GetPrimaryKeyValue(DbEntityEntry entry);

或者应该如何实现?

【问题讨论】:

    标签: c# entity-framework-4.1


    【解决方案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;
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-09-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-15
          • 1970-01-01
          • 2011-11-07
          • 2016-10-17
          相关资源
          最近更新 更多