Can I create a bidirectional foreign key relationship using Entity Framework Code First data annotations?

Steven Rands

I'm using EF 6 Code First and trying to figure out the best way to configure my relationships using data annotations, but for some reason EF is adding extra columns to the schema that I don't want.

I have two entities: Ship and Voyage. A ship can have many voyages; a voyage belongs to one and only one ship. So I started out with this (simplified for SO purposes):

public class Ship
{
    public int Id { get; set; }
    public virtual ICollection<Voyage> Voyages { get; set; }
}

public class Voyage
{
    public int Id { get; set; }
    public int ShipId { get; set; }
    public virtual Ship Ship { get; set; }
    public DateTimeOffset Started { get; set; }
}

This creates two tables in the database, as follows:

CREATE TABLE [dbo].[Ship] (
    [Id]                INT                IDENTITY (1, 1) NOT NULL,
    CONSTRAINT [PK_dbo.Ship] PRIMARY KEY CLUSTERED ([Id] ASC)
);

CREATE TABLE [dbo].[Voyage] (
    [Id]               INT                IDENTITY (1, 1) NOT NULL,
    [ShipId]           INT                NOT NULL,
    [Started]          DATETIMEOFFSET (7) NOT NULL,
    CONSTRAINT [PK_dbo.Voyage] PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [FK_dbo.Voyage_dbo.Ship_ShipId] FOREIGN KEY ([ShipId]) REFERENCES [dbo].[Ship] ([Id]) ON DELETE CASCADE
);

So far, so good. The problem comes when I want to query this data. I need to obtain a list of ships, but for each ship I want the most recent voyage as well. I couldn't see a way of writing a LINQ query that would do this in one hit, even though I would be able to write such a query using SQL.

My options at this point seemed to be:

  • Load all ships, and for each ship eagerly load all of its voyages. I didn't want to do this because of the performance implications (each ship may ultimately have lots of voyages)
  • Load all ships first, then foreach over the resulting list and perform a separate query for each ship to load its "most recent" voyage. Although this works it seems kind of inefficient compared to a single query.

I then thought I could add a navigation property to the Ship entity that would be used to reference directly the "most recent" voyage. So I tried this:

public class Ship
{
    public int Id { get; set; }
    public virtual ICollection<Voyage> Voyages { get; set; }
    public int? MostRecentVoyageId { get; set; }    <-- new property added
    public virtual Voyage MostRecentVoyage { get; set; }    <-- new property added
}

I made MostRecentVoyageId nullable because a ship will not have any voyages at all when it is first created.

This gives me the following in the database:

CREATE TABLE [dbo].[Ship] (
    [Id]                  INT                IDENTITY (1, 1) NOT NULL,
    [MostRecentVoyageId]  INT                NULL,
    CONSTRAINT [PK_dbo.Ship] PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [FK_dbo.Ship_dbo.Voyage_MostRecentVoyageId] FOREIGN KEY ([MostRecentVoyageId]) REFERENCES [dbo].[Voyage] ([Id])
);

which is fine for the Ship table, but I get this for the Voyage table:

CREATE TABLE [dbo].[Voyage] (
    [Id]               INT                IDENTITY (1, 1) NOT NULL,
    [ShipId]           INT                NOT NULL,
    [Started]          DATETIMEOFFSET (7) NOT NULL,
    [Ship_Id]          INT                NULL,
    CONSTRAINT [PK_dbo.Voyage] PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [FK_dbo.Voyage_dbo.Ship_ShipId] FOREIGN KEY ([ShipId]) REFERENCES [dbo].[Ship] ([Id]) ON DELETE CASCADE,
    CONSTRAINT [FK_dbo.Voyage_dbo.Ship_Ship_Id] FOREIGN KEY ([Ship_Id]) REFERENCES  [dbo].[Ship] ([Id])
);

Note the extra Ship_Id column and the additional foreign key relationship. I'm pretty certain that this column isn't needed, but I can't find a way of getting rid of it. I've tried using the [ForeignKey] and [InverseProperty] attributes but these just give me an exception.

Is this the kind of relationship I can't configure using EF data annotations? Do I have to use the fluent syntax for this? Am I doing it all wrong anyway: is there a better way to do the LINQ queries using my original entity types?

I have tried looking on SO for people having similar problems and I found this, this and this but none of those seemed to help.

Ben Robinson

I had almost the exact same model but in a different context and I got rid of the unwanted column in the database by doing the equivalent of adding [ForeignKey("MostRecentVoyage")] attribute to MostRecentVoyageId and adding [InverseProperty("Ship")] attribute to the Voyages property both on the Ship entity/class.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Entity Framework - Code first - Data annotations - Unnecessary foreign key columns

From Dev

Entity framework code first cant create primary and foreign key relationship

From Dev

Defining Self Referencing Foreign-Key-Relationship Using Entity Framework 7 Code First

From Dev

Foreign key relationship missing in ASP.NET MVC app using code-first approach with Entity Framework

From Dev

How do I create multiple 1:1 foreign key relationships in Entity Framework 6 Code First?

From Dev

Exchanged Foreign Key on Entity Framework Code First From data base

From Dev

Get foreign key value using Entity Framework code first

From Dev

Entity Framework, Code First: How can i make a Foreign Key Not-Nullable

From Dev

Entity Framework Code First Foreign Key issue

From Dev

Entity Framework Code First Foreign Key issue

From Dev

Foreign Key in Code First Entity Framework

From Dev

Entity Framework: Foreign Key in code first

From Dev

Create Foreign Key using Data Annotations

From Dev

Entity Framework 6 multiple table to one foreign key relationship code first

From Dev

Create a complex Primary Key using Entity Framework code-first

From Dev

Entity Framework code first can't update database after setting foreign key as nullable

From Dev

In Entity Framework code first, to map a navigation property do I also need to map the foreign key column

From Dev

Defining multiple Foreign Key for the Same table in Entity Framework Code First

From Dev

Entity Framework Code First Foreign Key adding Index as well

From Dev

Entity Framework 6 Code First Foreign Key Without Corresponding Properties

From Dev

Entity Framework Code First and Firebird - Foreign Key name issue

From Dev

Entity Framework Code first adds unwanted foreign key column

From Dev

Multiple Foreign Key for Same table in Entity Framework Code First

From Dev

Entity Framework one to optional foreign key code first fluent mapping

From Dev

Entity framework code first, get access to foreign key value

From Dev

Entity framework code first, custom foreign key name for inheritance

From Dev

How to specify a foreign key with code-first Entity Framework

From Dev

Entity Framework - Code First - Relationship

From Java

How to add foreign key relationship in Entity Framework?

Related Related

  1. 1

    Entity Framework - Code first - Data annotations - Unnecessary foreign key columns

  2. 2

    Entity framework code first cant create primary and foreign key relationship

  3. 3

    Defining Self Referencing Foreign-Key-Relationship Using Entity Framework 7 Code First

  4. 4

    Foreign key relationship missing in ASP.NET MVC app using code-first approach with Entity Framework

  5. 5

    How do I create multiple 1:1 foreign key relationships in Entity Framework 6 Code First?

  6. 6

    Exchanged Foreign Key on Entity Framework Code First From data base

  7. 7

    Get foreign key value using Entity Framework code first

  8. 8

    Entity Framework, Code First: How can i make a Foreign Key Not-Nullable

  9. 9

    Entity Framework Code First Foreign Key issue

  10. 10

    Entity Framework Code First Foreign Key issue

  11. 11

    Foreign Key in Code First Entity Framework

  12. 12

    Entity Framework: Foreign Key in code first

  13. 13

    Create Foreign Key using Data Annotations

  14. 14

    Entity Framework 6 multiple table to one foreign key relationship code first

  15. 15

    Create a complex Primary Key using Entity Framework code-first

  16. 16

    Entity Framework code first can't update database after setting foreign key as nullable

  17. 17

    In Entity Framework code first, to map a navigation property do I also need to map the foreign key column

  18. 18

    Defining multiple Foreign Key for the Same table in Entity Framework Code First

  19. 19

    Entity Framework Code First Foreign Key adding Index as well

  20. 20

    Entity Framework 6 Code First Foreign Key Without Corresponding Properties

  21. 21

    Entity Framework Code First and Firebird - Foreign Key name issue

  22. 22

    Entity Framework Code first adds unwanted foreign key column

  23. 23

    Multiple Foreign Key for Same table in Entity Framework Code First

  24. 24

    Entity Framework one to optional foreign key code first fluent mapping

  25. 25

    Entity framework code first, get access to foreign key value

  26. 26

    Entity framework code first, custom foreign key name for inheritance

  27. 27

    How to specify a foreign key with code-first Entity Framework

  28. 28

    Entity Framework - Code First - Relationship

  29. 29

    How to add foreign key relationship in Entity Framework?

HotTag

Archive