As I understand it (so please correct me if I am mistaken), entity classes that have relationships between them can be defined in several ways -- (1) by using both a property to represent a scalar key plus a navigation property or (2) just using a navigation property.
If you use Data Annotations I believe that your only choice is using both the scalar key and navigation properties whereas using Fluent API both approaches are available.
My question is which approach to take? What are the pros and cons of each? (This is in regard to the two choices regarding foreign keys and navigation properties...not regarding Data Annotations vs. Fluent.
As I see it it boils down to these factors/concerns
Am I missing anything? In general, what is the recommended way of defining the foreign keys and navigation properties? Why even offer both approaches as it seems to muddle the waters? I have looked at a lot of tutorials and see a mix of both approaches.
Thank you.
(1) by using both a property to represent a scalar key plus a navigation property or (2) just using a navigation property.
That is difference between foreign key and independent associations.
If you use Data Annotations I believe that your only choice is using both the scalar key and navigation properties whereas using Fluent API both approaches are available.
No. Data annotations are just another hints. Navigation properties are recognized by default conventions automatically.
Having both a scalar property and a navigation property could be seen as "dirtying up" the class.
Yes but due to different nature of two association types having scalar property makes some development tasks simpler.
Having just the navigation property would require an Includes() call to get access to the FK value. I have not looked at the SELECT statement being sent but I would suspect that a JOIN is being executed and data that is not needed is being sent back.
Yes. Include
means fetching data but you don't need to use it if you need access to FK only in linq-to-entities query. Example:
var children = from c in context.Children
where c.Parent.Id == 123
select c;
This query access "FK" through Parent
and internally generates join but does not fetch parent.
Having the scalar property would preclude the need for Include() calls.
No. Include
is dependent on navigation property and FK property itself doesn't create association. You always must have navigation property on at least one side of the relation (either in Parent
or Child
in my example).
it looks like navigation properties cannot be used as part of a composite key
Yes. If you need composite key you need to expose foreign keys on your entity.
There is additional related question.