Подтвердить что ты не робот

EntityFramework 6 Как получить поле идентификации с отражением?

У меня есть общий метод с параметром типа T, где T - тип объекта в EF-модели. Мне нужно получить имя поля идентификации в этом типе. Я видел эту статью: Есть ли способ получить имя идентификатора объекта с помощью отражения или что-то еще? Но я не могу понять, о чем говорит Тевин, когда он говорит о типах EntitySetBase и EntityTypeBase. Если EntityTypeBase является типом одного из объектов в модели, значит, у EF6 нет свойства KeyMembers.

4b9b3361

Ответ 1

Я не думаю, что можно получить первичные ключи только путем отражения.

Во-первых, давайте узнаем, как EF определяет, какое свойство (и) будет являться первичным ключом (-ами) независимо от порядка/приоритета

Соглашение с Entity Framework для первичных ключей:

  • Ваш класс определяет свойство с именем "ID" или "Id"
  • или имя класса, за которым следуют "ID" или "Id"

Мы можем использовать GetProperties и сравнить имя свойства.

var key = type.GetProperties().FirstOrDefault(p => 
    p.Name.Equals("ID", StringComparison.OrdinalIgnoreCase) 
    || p.Name.Equals(type.Name + "ID", StringComparison.OrdinalIgnoreCase));

Мы можем использовать CustomAttributes и сравнивать тип атрибута.

var key = type.GetProperties().FirstOrDefault(p => 
    p.CustomAttributes.Any(attr => attr.AttributeType == typeof(KeyAttribute)));

Это трудная задача, modelBuilder инкапсулируется в OnModelCreating, и даже если мы сохраним modelBuilder где-то как свойство field/property, все еще сложно извлечь ключ из функции HasKey все инкапсулировано. Вы можете проверить исходный код . И все в EF зависит от ObjectContext и после вызова ObjectContext, например, этой строки кода,

((IObjectContextAdapter)context).ObjectContext

тогда будет создано соединение с базой данных, вы можете проверить с помощью профилировщика. И вот фрагмент кода исходного кода.

public override ObjectContext ObjectContext
{
    get
    {
        Initialize();
        return ObjectContextInUse;
    }
}

public void Initialize()
{
    InitializeContext();
    InitializeDatabase();
}

Поэтому, в настоящее время единственный возможный способ получить первичный ключ - через набор объектов, набор объектов, членов ключа и т.д., как описано в этот пост

var keyNames = set.EntitySet.ElementType.KeyMembers.Select(k => k.Name);