В первую очередь влияет на именование столбцов внешнего ключа в EF-коде (CTP5)
У меня есть класс POCO, который имеет два односторонних унарных отношений с другим классом, оба класса совместно используют предка. Имена внешних ключей в сгенерированной схеме не отражают имена свойств. (Свойства MainContact и FinancialContact дают имена полей PersonId и PersonId1).
Как я могу повлиять на создание схемы для создания имен столбцов базы данных, которые соответствуют именам свойств?
Модель выглядит следующим образом:
![The class model]()
Код выглядит следующим образом:
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; }
}
Схема выглядит следующим образом:
![enter image description here]()
Ответ от druttka
druttka ответ ниже выполнил эту работу, и приятно узнать, что это ошибка CTP5, которая стоит за этим. EF также нуждается в каскадном поведении, которое должно быть указано, и я использовал свободный API для этого, следуя примеру в ссылке, приведенной druttka. Еще более хорошее чтение из Morteza Manavi здесь.
Теперь это код:
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; }
}
Что теперь дает гораздо более подходящую базу данных:
![enter image description here]()
Ответы
Ответ 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; }
}