簡體   English   中英

我可以使用Entity Framework Code First數據注釋創建雙向外鍵關系嗎?

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

我正在使用EF 6 Code First,並試圖找出使用數據批注配置我的關系的最佳方法,但是由於某些原因,EF向我不需要的架構添加了額外的列。

我有兩個實體: ShipVoyage 一艘船可以航行很多次。 一次航行屬於一艘並且只有一艘船。 因此,我從這里開始(出於SO的目的而簡化):

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; }
}

這將在數​​據庫中創建兩個表,如下所示:

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
);

到現在為止還挺好。 問題出在我要查詢此數據時。 我需要獲取船只清單,但對於每艘船只,我也希望最近一次航行。 即使我能夠使用SQL編寫這樣的查詢,我也看不出一種可以一口氣做到這一點的LINQ查詢的方法。

在這一點上,我的選擇似乎是:

  • 裝載所有船舶,並為每個船舶熱切裝載其所有航程。 由於性能方面的原因,我不想這樣做(每艘船最終可能會有很多航行)
  • 首先加載所有船只,然后foreach結果列表,並對每個船只執行單獨的查詢以加載其“最近”航行。 盡管此方法有效,但與單個查詢相比似乎效率低下。

然后我以為可以將導航屬性添加到Ship實體,該實體將用於直接引用“最新”航程。 所以我嘗試了這個:

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
}

我將MostRecentVoyageId可空,因為船舶在首次創建時將完全沒有任何航程。

這為我提供了數據庫中的以下內容:

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])
);

這對於Ship表來說很好,但是對於Voyage表我可以做到這一點:

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])
);

請注意額外的Ship_Id列和額外的外鍵關系。 我可以肯定不需要此專欄,但是我找不到擺脫它的方法。 我已經嘗試過使用[ForeignKey][InverseProperty]屬性,但是這些只是給我一個例外。

我無法使用EF數據注釋配置這種關系嗎? 為此,我是否必須使用流利的語法? 無論如何,我是否都做錯了:是否有更好的方法使用原始實體類型來進行LINQ查詢?

我嘗試過為有類似問題的人尋找SO,我發現了這個這個這個,但似乎沒有一個幫助。

我有幾乎完全相同的模型,但是在不同的上下文中,並且通過將[ForeignKey("MostRecentVoyage")]屬性添加到MostRecentVoyageId並添加[InverseProperty("Ship")]擺脫了數據庫中不需要的列都在Ship實體/類上同時具有Voyages屬性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM