Entity Framework 4.1 Кодирует идентификаторы первого внешнего ключа

#c# #poco #entity-framework-4.1

#c# #poco #entity-framework-4.1

Вопрос:

У меня есть две сущности, ссылающиеся одна на другую. Когда entity Framework создала таблицу, она создает два внешних ключа, один для ключа, который я указал в интерфейсе fluent, а другой для ICollection. Как мне избавиться от дубликата внешнего ключа?

 public class Person
{
    public long RecordId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public string Username { get; set; }

    public long DepartmentId { get; set; }
    public virtual Department Department { get; set; }
}

public class Department
{
    public long RecordId { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Person> People { get; set; }
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Person>()
        .HasRequired(p => p.Department)
        .WithMany()
        .HasForeignKey(p => p.DepartmentId)
        .WillCascadeOnDelete(false);
}
  

Спасибо!

Ответ №1:

Вы должны явно указать множество концов ассоциации:

 modelBuilder.Entity<Person>()
    .HasRequired(p => p.Department)
    .WithMany(d => d.People)
    .HasForeignKey(p => p.DepartmentId)
    .WillCascadeOnDelete(false);
  

В противном случае EF будет считать, что существуют две ассоциации: одна, которая не предоставляется в Department с внешним ключом DepartmentId и свойством навигации Department в Person классе, как вы определили в коде Fluent, — и другая ассоциация, которая принадлежит предоставленному свойству навигации People , но с другим не предоставленным концом в Person и внешним ключом, автоматически созданным EF. Это другой ключ, который вы видите в базе данных.

Комментарии:

1. Может ли это сработать ???: [ForeignKey(«Department»)] общедоступный длинный идентификатор департамента { получить; установить; }

2. @billy: Это не на 100% одно и то же, потому что аннотации не отключают каскадное удаление. Если вы не хотите отключать каскадное удаление, то это работает, да. Но тогда вам даже не понадобятся аннотации, потому что соглашения об именовании автоматически определят свойство внешнего ключа.

Ответ №2:

Соглашения Code First по умолчанию определяют внешний ключ вашего DepartmentID, поскольку он, ну, обычный. Я думаю, вам следует удалить определение Fluent:

 modelBuilder.Entity<Person>()
    .HasRequired(p => p.Department)
    .WithMany()
    .WillCascadeOnDelete(false);
  

Ответ №3:

лучше всего удалить свойство departmentid из класса Person и добавить следующий оператор. MapKey создаст столбец внешнего ключа с указанным вами именем

  modelBuilder.Entity<Person>().HasRequired(p =>  p.Department)
    .WithMany().Map(x=>x.MapKey("DepartmentId"))
    .WillCascadeOnDelete(false);
  

Комментарии:

1. Я пробовал этот подход, но он вызвал исключение при запуске Seed() метода, ссылающегося на имя столбца по умолчанию, а не на то, которое указано в MapKey() .