I have a POCO class that has two one-way unary relationships with another class, both classes share an ancestor. The names of the foreign keys in the generated schema do not reflect the property names. (Properties MainContact and FinancialContact give PersonId and PersonId1 field names).
How can I influence schema generation to generate database column names that match the property names?
The model looks like this:
The code looks like this:
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; }
}
The schema looks like this:
druttka's answer below did the job and it's nice to know that it's a CTP5 bug that's behind this. EF also needs the cascade behaviour to be specified and I've used the fluent API to do this following the example in the link given by druttka. Some more good reading from Morteza Manavi here.
The code now is this:
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; }
}
Which now gives the far more suitable database:
To create Foreign Key, you need to use ForeignKey attribute with specifying the name of the property as parameter. You also need to specify the name of the table which is going to participate in relationship. I mean to say, define the foreign key table. Thanks for reading this article, hope you enjoyed it.
A foreign key can also have different column names than the primary key. The foreign key and primary key can also have different default values. However, since values in the referenced table must be unique, default values are not much used and are rarely used for columns that are part of a primary key.
A foreign key is an attribute that completes a relationship by identifying the parent entity. Foreign keys provide a method for maintaining integrity in the data (called referential integrity) and for navigating between different instances of an entity.
EF Code First uses, by default, convention over configuration. However, you can set explicit alternatives by overriding DbContent.OnModelCreating. Many examples here, courtesy of ScottGu.
EDIT
So in CTP5, MapSingleType went away as described here. The following works for simple string properties, but not for your Organisation to Person relationships. I'm curious and plan to keep looking at it, but in the meantime, maybe this will get your started or someone else can complete the answer.
public class Person : Customer
{
[Column(Name="EmailAddress")]
public string Email { get; set; }
}
EDIT 2
Ok, this gets it. Found the answer here. Disclaimer: I've only verified that the database schema is created as expected. I have not tested that seeding data or further CRUD operations work as expected.
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; }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With