9

When looking at questions and answers on this site and reading some of the top Google-ranked tutorials on Code First development I frequently see the following pattern...

public class Category
{
    public Category()
    {
        Products = new Collection<Product>();
    }
    public Guid ID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Product> Products { get; set; }
}

public class Product
{
    public Guid ID { get; set; }
    public string Name { get; set; }
    public DateTime DateAdded { get; set; }
    public Guid CategoryID { get; set; } // Seemingly redundant property
    public virtual Category Category { get; set; }
}

When searching for Code First tutorials the following two pages come up that use this same pattern:

http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4.aspx

http://www.codeproject.com/Articles/327945/Architecture-Guide-ASP-NET-MVC3-Entity-Framework-C

Question: So what is the point of having the foreign key property on the Code First C# object? In the above example you can omit CategoryID from the Product class and everything will work just fine. The foreign key Category_ID will still be created in the database.

The only thing I could think of is that people might like to be able to specify whether the relationship is optional using nullable types instead of the fluent API, but I think it really confuses things to have both a Category and CategoryID property.

So before I go around and remove all my foreign key properties, is there anything that I'm missing here? What's the point of doing this?

Thanks!

Jeff Camera
  • 5,324
  • 5
  • 44
  • 59
  • I think that making it a `Guid?` makes a dfference. Some DataAnnotations might apply. – H H Feb 12 '12 at 22:25
  • Yes I mentioned that in my question... anything that can't be done using the fluent API though? Seems pretty evil to have two essentially duplicate properties when you don't have to. – Jeff Camera Feb 12 '12 at 22:31
  • Possible duplicate of [Code First: Independent associations vs. Foreign key associations?](https://stackoverflow.com/questions/5281974/code-first-independent-associations-vs-foreign-key-associations) – Michael Freidgeim Feb 16 '18 at 07:20

1 Answers1

9

Yes, I think there is no need for foreign key properties and they are somehow a relational artifact in the object world. You can define relationships completely without FK properties. In Fluent API you can define if the relationship is optional or required and you can specify the database table's foreign key column name. The relationship is then called Independent Association.

My understanding is that Foreign Key Associations - relationships with exposed foreign key properties in your model class - only exist to make working with relationships in Entity Framework a bit easier and more comfortable in certain scenarios. For example:

Suppose you have a web view to create or edit a product and the view contains a combobox to select a category and assign it to the product. To fill the combobox when the view is rendered you would load, for instance, the ID and the Name of all categories from the database.

When the page is posted back you would receive the properties for the product and the ID of the selected category. If you don't have a foreign key property CategoryID in your Product you would have to create the relationship this way:

var category = new Category { ID = IDFromComboBox };
context.Categories.Attach(category);
product.Category = category;

With a FK property you only need one line:

product.CategoryID = IDFromComboBox;

Foreign key properties didn't exist in Entity Framework version 1 (.NET 3.5) and have been introduced with EF version 4 (.NET 4) to support scenarios like the above better.

A critical view on Foreign Key Association can be found and the difference between the two types of associations is very well discussed in Ladislav's blog:

http://www.ladislavmrnka.com/2011/05/foreign-key-vs-independent-associations-in-ef-4/

Slauma
  • 175,098
  • 59
  • 401
  • 420
  • Thanks for the in-depth response and blog reference. Maybe I am missing something from your example though... If you populate a combobox with categories from the database and the form is posted back with the selected category ID wouldn't you attempt to pull the category from the database (`var category = db.Single(x => x.ID == id);`), perform validation, and then assign the category by simply going `product.Category = category`? – Jeff Camera Feb 12 '12 at 23:23
  • @JohntheRevelator: Yes, that's the alternative. But it would required an additional database roundtrip. You don't need this roundtrip if you have the ID, that's what `Attach` is for. Validation is a good point though, you mean validation if the category with the posted ID exists at all, right? You could still do it with `if (db.Categories.Any(x => x.ID == id)) ...` which just returns a `bool` and would be cheaper than returning the full category. – Slauma Feb 12 '12 at 23:34