Влияние на имена столбцов внешнего ключа в первую очередь в коде EF (CTP5)

У меня есть класс POCO, который имеет две односторонние унарные отношения с другим классом, оба класса имеют общего предка. Имена внешних ключей в сгенерированной схеме не отражают имена свойств. (Свойства MainContact и FinancialContact задают имена полей PersonId и PersonId1).

Как я могу повлиять на создание схемы, чтобы создать имена столбцов базы данных, соответствующие именам свойств?

Модель выглядит так:

Модель класса

Код выглядит следующим образом:

public class CustomerContext: DbContext
{
   public DbSet<Organisation> Organisations { get; set; }
   public DbSet<Person> Persons { get; set; }

   protected override void OnModelCreating(ModelBuilder builder)
   {
      DbDatabase.SetInitializer(new DropCreateDatabaseAlways<CustomerContext>());
   }
}

public abstract class Customer
{
   public int Id { get; set; }
   public string Name { get; set; }
}

public class Person : Customer
{
   public string Email { get; set; }
}

public class Organisation : Customer
{
   public Person FinancialContact { get; set; }
   public Person MainContact { get; set; }
}

Схема выглядит так: введите здесь описание изображения

Ответ от Друтка


Ответ druttka ниже сделал свое дело, и приятно знать, что за этим стоит ошибка CTP5. EF также необходимо указать каскадное поведение, и я использовал свободный API для этого, следуя примеру в ссылке, указанной druttka. Еще немного хорошего чтения от Мортезы Манави здесь.

Код теперь такой:

public class CustomerContext : DbContext
{
   public DbSet<Organisation> Organisations { get; set; }
   public DbSet<Person> Persons { get; set; }

   protected override void OnModelCreating(ModelBuilder builder)
   {
      DbDatabase.SetInitializer(new DropCreateDatabaseAlways<CustomerContext>());

      builder.Entity<Organisation>()
         .HasRequired(p => p.MainContact)
         .WithMany()
         .HasForeignKey(p => p.MainContactId)
         .WillCascadeOnDelete(false);
      builder.Entity<Organisation>()
         .Property(p => p.MainContactId)
         .HasColumnName("MainContact");

      builder.Entity<Organisation>()
         .HasRequired(p => p.FinancialContact)
         .WithMany()
         .HasForeignKey(p => p.FinancialContactId)
         .WillCascadeOnDelete(false);
      builder.Entity<Organisation>()
         .Property(p => p.FinancialContactId)
         .HasColumnName("FinancialContact");
   }
}

public abstract class Customer
{
   public int Id { get; set; }
   public string Name { get; set; }
}

public class Person : Customer
{
   public string Email { get; set; }
}

public class Organisation : Customer
{
   public Person FinancialContact { get; set; }
   public int FinancialContactId { get; set; }

   public Person MainContact { get; set; }
   public int MainContactId { get; set; }
}

Что теперь дает гораздо более подходящую базу данных: введите здесь описание изображения


person Sean Kearon    schedule 22.02.2011    source источник
comment
Использовать атрибуты, чтобы отразить, что ваша схема базы данных плохо названа?   -  person Claus Jørgensen    schedule 24.02.2011
comment
дайте мне знать, если EDIT 2 моего ответа сработает для вас. Как я уже сказал, я проверил, что БД создается, как и ожидалось, но не тестировал дальнейшие операции CRUD, поэтому мне интересно узнать, правильно ли она себя ведет.   -  person David Ruttka    schedule 24.02.2011


Ответы (1)


EF Code First по умолчанию использует соглашение, а не конфигурацию. Однако вы можете задать явные альтернативы, переопределив DbContent.OnModelCreating. Множество примеров здесь, любезно предоставлено ScottGu.

ИЗМЕНИТЬ

Таким образом, в CTP5 MapSingleType исчез, как описано здесь. Следующее работает для простых строковых свойств, но не для отношений «Организация-человек». Мне любопытно, и я планирую продолжать смотреть на это, но тем временем, может быть, это поможет вам начать или кто-то другой сможет завершить ответ.

public class Person : Customer
{
    [Column(Name="EmailAddress")]
    public string Email { get; set; }
}

ИЗМЕНИТЬ 2

Хорошо, это понятно. Ответ найден здесь. Отказ от ответственности: я только проверил, что схема базы данных создана должным образом. Я не проверял, что данные заполнения или дальнейшие операции CRUD работают должным образом.

public class Organisation : Customer
{
    [Column(Name = "FinancialContact")]
    public int? FinancialContactId { get; set; }
    [ForeignKey("FinancialContactId")]
    public Person FinancialContact { get; set; }
    [Column(Name = "MainContact")]
    public int? MainContactId { get; set; }
    [ForeignKey("MainContactId")]
    public Person MainContact { get; set; }
}
person David Ruttka    schedule 24.02.2011
comment
Я постараюсь попробовать и скоро опубликую явный образец. - person David Ruttka; 24.02.2011
comment
druttka - спасибо за ответ, это помогает. Я обновил свой ответ, чтобы показать новый код. Мне также пришлось добавить обратное свойство для каждого свойства организации, так как мне нужно указать каскадное поведение, и я использовал версию API Fluent вместо атрибутов, которые вы использовали. Я очень ценю вашу помощь в этом :) - person Sean Kearon; 24.02.2011
comment
Обновление - вам не нужны обратные свойства (что хорошо!). См. сообщение Мортезы Манави здесь: weblogs.asp.net/manavi/archive/2011/01/23/ - person Sean Kearon; 24.02.2011