Let's say I have the following classes, auto generated by Entity Framework
, that have an association:
public class Parent()
{
public int ParentID { get; set; } // PK
public int ChildID { get; set; } // FK
public string Description { get; set; }
public Child Child { get; set; } // Navigation property
}
public class Child()
{
public int ChildID { get; set; } // PK
public Parent Parent { get; set; } // Navigation property
}
enter image description here
As you can see, the Parent class contains a foreign key property to the Child class.
Now, let's say I want to retrieve some data from my database with LINQ
. What I would do is create a custom class (model) so that I don't have to work with the auto generated classes (I can easily add more properties, methods,...).
public class ChildModel()
{
public int ChildID { get; set; }
// More properties/methods
}
When creating the ParentModel class, I have two ways of creating this class:
A class with both the property ChildID and a navigation property Child.
public class ParentModel()
{
public int ParentID { get; set; }
public int ChildID { get; set; }
public ChildModel Child { get; set; }
}
Or a class with only a navigation property Child and no ChildID property.
public class ParentModel()
{
public int ParentID { get; set; }
public ChildModel Child { get; set; }
}
With the second method, I always have to create an extra class when I only need the ChildID, with the second method I don't have to. But when I do create the ChildModel, I have to initialize both ChildIDs so that I don't run into any problems later.
What would be the best way to create my model classes? With or without the foreign key? Are there any advantages/disadvantages when using one of the two methods described above?
2 Answers 2
Using both childId
and Child property seems to be the worst option because of potential mistakes / inconsistencies.
Having only the Navigation property seems best option for several reasons:
If the relationship is optional you have a clear indication that there is no child by setting the property to
null
. In case you have onlychildId
, you need to set it to some magic number like -1 or 0, which is less elegant I suppose, or make itint?
type which isn't a better solution either.With Navigation property you can implement several features like automatic lazy loading.
Your objects stay abstract to the actual storage and relationship implementation.
Microsoft recommends using both, although your example looks like you have the foreign key on the wrong class. I would have expected the Child class to be dependant on the Parent. The parent class doesn't need the foreign key because it's not dependant on its children.
To quote Microsoft: In addition to navigation properties, we recommend that you include foreign key properties on the types that represent dependent objects.
https://msdn.microsoft.com/en-nz/data/jj679962.aspx
public class ParentModel()
{
public int ParentID { get; set; }
//navigation property
public ChildModel Child { get; set; }
}
public class ChildModel()
{
public int ChildID { get; set; }
// More properties/methods
//foreign key
public int ParentID { get; set; }
//navigation property
public ParentModel Parent { get; set; }
}
-
Why Microsoft recommends that? Another question rising is, are the foreign-key properties initialized even if the entity itself uses lazy loading? Then there was a real benefit of also adding the fk property.Tim Schmelter– Tim Schmelter2019年01月28日 09:07:49 +00:00Commented Jan 28, 2019 at 9:07
public List<ChildModel> Children { get; set; }