Entity Framework 4.1 InverseProperty Attribute
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;}
}
Solution 1:
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.)
Solution 2:
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.