Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the syntax for self referencing foreign keys in EF Code First?

I am trying to reference a foreign key from SpouseId to Id in the Contact table. What is the syntax for doing this? I can't seem to find an example. Thanks.

I have a class like this:

public class Contact {     public int Id {get;set;}     public string Name {get;set;}     public int? SpouseId {get;set;} } 

EDIT1 Per the link provided by Joel Cunningham and the answer from Morteza I have added some additional code.

ContactMap.cs

public partial class ContactMap : EntityTypeConfiguration<Contact> {   public ContactMap()      {        this.ToTable("Contact");        this.HasKey(c => c.Id);        this.HasOptional(c => c.Spouse)            .WithMany()            .IsIndependent()            .Map(m => m.MapKey(fk => fk.Id, "SpouseId"));      } } 

MyObjectContext.cs

public class MyObjectContext : DbContext, IDbContext {   public DbSet<Contact> Contacts {get;set;}   protected override void OnModelCreating(ModelBuilder modelBuilder)      {         modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();         modelBuilder.Configurations.Add(new ContactMap());      } } 

Note: I also added the "[ForeignKey("SpouseId")]" attribute to my Spouse property in my Contact class. Unfortunately I keep getting "Sequence contains more than one matching element".

EDIT2: Morteza's answers below is correct. To summarize: For self referencing foreign keys you can either mark the property as a "[ForeginKey("SpouseId")] OR use the fluent API example below. The errors I reported in some of my comments were caused by my unit test. EF generated the db the correct way. I found a good link where Craig Stuntz outlined why auto-increment keys and self-referencing foreign keys can cause the "Unable to determine a valid ordering for dependent operations" error. I believe this is what my problem is. Hope this helps someone.

like image 714
trevorc Avatar asked Jan 26 '11 23:01

trevorc


People also ask

How do you mention foreign key in code first approach?

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.

How do you set a foreign key in EF?

The [ForeignKey(name)] attribute can be applied in three ways: [ForeignKey(NavigationPropertyName)] on the foreign key scalar property in the dependent entity. [ForeignKey(ForeignKeyPropertyName)] on the related reference navigation property in the dependent entity.

What is self referencing foreign key in MySQL?

Self Referencing Foreign Key is also known as Recursive Foreign Key. It defines the relationship between the same entity or table. and all others properties of normal foreign key constraint in MySQL.


1 Answers

Something like this will work:

public class Contact {     public int Id {get;set;}     public string Name {get;set;}     public int? SpouseId {get;set;}      [ForeignKey("SpouseId")]     public Contact Spouse {get;set;} } 

ForeignKeyAttribute has been added to System.ComponentModel.DataAnnotations by CTP5 assembly.

Update I: CTP5 Bug:

Due to a bug in CTP5, creating an Independent Self Referencing Associations throws an exception. The workaround is to use Foreign Key Associations instead (which is always recommended regardless).

Update II: Using Fluent API to Configure a Self Referencing Association:

You can also use fluent API to achieve this, if you prefer:

public class Contact {     public int Id { get; set; }     public string Name { get; set; }     public int? SpouseId { get; set; }                      public Contact Spouse { get; set; } }  public class Ctp5Context : DbContext {     public DbSet<Contact> Contacts { get; set; }      protected override void OnModelCreating(ModelBuilder modelBuilder)     {         modelBuilder.Entity<Contact>()                     .HasOptional(c => c.Spouse)                     .WithMany()                     .HasForeignKey(c => c.SpouseId);     } } 

Working with the Model:

using (var context = new Ctp5Context()) {     Contact contact = new Contact()     {         Name = "Morteza",         Spouse = new Contact()         {             Name = "Code-First"         }     };     context.Contacts.Add(contact);     context.SaveChanges(); } 
like image 87
Morteza Manavi Avatar answered Sep 22 '22 11:09

Morteza Manavi