Search code examples
entity-frameworkdata-annotationsfluent-interface

Need clarification on Entity Framework Code-First and Navigation Properties and Scalar Keys


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

  1. Having both a scalar property and a navigation property could be seen as "dirtying up" the class.
  2. 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.
  3. Having the scalar property would preclude the need for Include() calls.
  4. As hinted in a previous SO question from me (related question), it looks like navigation properties cannot be used as part of a composite key so one would be forced to include the additional scalar key. And if you have to do it for one property it would make sense to be consistent in all your classes.

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.


Solution

  • (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.