Сначала получить значение первичного ключа для произвольного объекта в коде

Есть ли такой метод?

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.

Ответ 2

Я также ищу, чтобы найти первичный ключ объекта. Я использую Generics в моем репозитории, поэтому я не знаю Entity до времени исполнения. Единственный способ, которым я нашел это до сих пор, - это сделать выражение 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
      }



    }
  }