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

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”的实体失败,因为同一类型的另一个实体已经具有相同的主键值

javaWeb_JDBC_JDBC获取数据库自动生成的主键值

获取mybaties插入记录自动增长的主键值

MyBatis 插入时返回刚插入记录的主键值

mybatis中useGeneratedKeys用法--插入数据库后获取主键值