38

Just wanted to know more about RelatedTo attribute and I found out it has been replaced by ForeignKey and InverseProperty attributes in EF 4.1 RC.

Does anyone know any useful resources about the scenarios that this attribute becomes useful?

Should I use this attribute on navigation properties? example:

public class Book
{
  public int ID {get; set;}
  public string Title {get; set;}

  [ForeignKey("FK_AuthorID")]
  public Author Author {get; set;}
}  

public class Author
{
  public int ID {get; set;}
  public string Name {get; set;}
  // Should I use InverseProperty on the following property?
  public virtual ICollection<Book> Books {get; set;}
}
Jacob
  • 3,598
  • 4
  • 35
  • 56
Kamyar
  • 18,639
  • 9
  • 97
  • 171

2 Answers2

81

I add an example for the InversePropertyAttribute. It cannot only be used for relationships in self referencing entities (as in the example linked in Ladislav's answer) but also in the "normal" case of relationships between different entities:

public class Book
{
    public int ID {get; set;}
    public string Title {get; set;}

    [InverseProperty("Books")]
    public Author Author {get; set;}
}

public class Author
{
    public int ID {get; set;}
    public string Name {get; set;}

    [InverseProperty("Author")]
    public virtual ICollection<Book> Books {get; set;}
}

This would describe the same relationship as this Fluent Code:

modelBuilder.Entity<Book>()
            .HasOptional(b => b.Author)
            .WithMany(a => a.Books);

... or ...

modelBuilder.Entity<Author>()
            .HasMany(a => a.Books)
            .WithOptional(b => b.Author);

Now, adding the InverseProperty attribute in the example above is redundant: The mapping conventions would create the same single relationship anyway.

But consider this example (of a book library which only contains books written together by two authors):

public class Book
{
    public int ID {get; set;}
    public string Title {get; set;}

    public Author FirstAuthor {get; set;}
    public Author SecondAuthor {get; set;}
}

public class Author
{
    public int ID {get; set;}
    public string Name {get; set;}

    public virtual ICollection<Book> BooksAsFirstAuthor {get; set;}
    public virtual ICollection<Book> BooksAsSecondAuthor {get; set;}
}

The mapping conventions would not detect which ends of these relationships belong together and actually create four relationships (with four foreign keys in the Books table). In this situation using the InverseProperty would help to define the correct relationships we want in our model:

public class Book
{
    public int ID {get; set;}
    public string Title {get; set;}

    [InverseProperty("BooksAsFirstAuthor")]
    public Author FirstAuthor {get; set;}
    [InverseProperty("BooksAsSecondAuthor")]
    public Author SecondAuthor {get; set;}
}

public class Author
{
    public int ID {get; set;}
    public string Name {get; set;}

    [InverseProperty("FirstAuthor")]
    public virtual ICollection<Book> BooksAsFirstAuthor {get; set;}
    [InverseProperty("SecondAuthor")]
    public virtual ICollection<Book> BooksAsSecondAuthor {get; set;}
}

Here we would only get two relationships. (Note: The InverseProperty attribute is only necessary on one end of the relationship, we can omit the attribute on the other end.)

Slauma
  • 175,098
  • 59
  • 401
  • 420
  • 1
    +1 Good. I hoped you will come and explain it little bit more to get some credits :) – Ladislav Mrnka Apr 19 '11 at 13:45
  • 7
    Lol! But somehow this attribute is in no-mans-land between conventions and Fluent mapping: For simple relationships it's not necessary and for complex relationships everyone will use Fluent code. Probably the reason why it's so uncommon and the only explanation I can think of why even *you* didn't know it :) – Slauma Apr 19 '11 at 14:48
  • 1
    Thanks for the insightful answer. – Kamyar Apr 20 '11 at 05:56
  • 3
    I've been googling this for a week. You are a god among men. – Jay Nov 16 '12 at 00:21
  • A little late but: Should `FirstAuthor` and `SecondAuthor` in `Book` be `virtual` too? In this case I believe you don't need the `Attribute` too. – Vitor Canova May 19 '16 at 17:01
  • expletive word - awesome!! Great tutorial and examples. First rate answer! – Richard Housham Jan 27 '17 at 11:17
28

ForeignKey attribute pairs FK property with navigation property. It can be placed either on FK property or navigation property. It is equivalent of HasForeignKey fluent mapping.

public class MyEntity
{
    public int Id { get; set; }

    [ForeignKey("Navigation")]
    public virtual int NavigationFK { get; set; }

    public virtual OtherEntity Navigation { get; set; }
}

InverseProperty is used for defining self referencing relation and pairing navigation properties on both ends. Check this question for sample.

Community
  • 1
  • 1
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • 2
    Ha! it's you again! Thanks EF guru! – Kamyar Apr 19 '11 at 13:00
  • So if I have a master detail scenario (EF4.2), what do I decorate the properties (do I have to)? Say I have a `Master` class with a virtual property `Detail:ICollection` and a `Detail` class with a virtual property `Master`. – Shimmy Weitzhandler Feb 07 '12 at 03:29