簡體   English   中英

實體框架:無效的列名 *_ID 即使使用流暢的 api 或數據注釋

[英]Entity Framework : Invalid column name *_ID even with fluent api or data annotations

我整天都在看的奇怪問題。 我正在使用 Entity Framework 6。我遇到的問題是我有三個實體:

public partial class Order : ILocationBearingObject
{
    public int Id { get; set; }
    // other properties and relationships here
    public int? OrderProfileId { get; set; }
    public int OrderTemplateId { get; set; }

    public virtual OrderProfile Profile { get; set; } // optional property
    public virtual OrderTemplate OrderTemplate{ get; set; }
}

public class OrderProfile 
{
    public int Id { get; set; }
    // other properties
    
    // added here 6/15/2021
    public virtual OrderTemplate OrderTemplate{ get; set; }
}

public class OrderTemplate : EntityMetaData
{
    public int Id { get; set; }
    // other properties

    public int? OrderProfileId{ get; set; }
    public OrderProfile OrderProfile { get; set; }
}

在我們的 model 構建器中,我們有以下定義:

modelBuilder.Entity<Order>()
    .HasOptional(x => x.OrderProfile)
    .WithMany(x => x.Orders)
    .HasForeignKey(x => x.OrderProfileId);

modelBuilder.Entity<OrderProfile>()
    .HasOptional(x => x.OrderTemplate)
    .WithOptionalPrincipal(x => x.OrderProfile);

但即使使用上述流暢的 api model,我們也會得到錯誤

列名“OrderProfile_Id”無效

在各種測試中,我無法找到為什么會出現這個問題,所以我查看了我們的日志,發現這個錯誤什么時候開始出現,然后能夠找到與 OrderProfile 關聯的更改,發現唯一的更改是正在添加從 OrderProfile 到 OrderTemplate 的關系。

當我刪除流利的 api 關系 OrderProfile 到 OrderTemplate 時,它按預期工作......我不需要與 OrderTemplate 的關系,但希望它在那里,我怎樣才能在不破壞其他關系的情況下建立可選的 1 到可選的 1 關系關系? 另外,為什么會影響其他關系?

更新 6/15/2021所以我發現我在 OrderProfile model 中有一個反向導航屬性:

public virtual OrderTemplate OrderTemplate{ get; set; }

刪除那個和相關的流暢關系

        modelBuilder.Entity<OrderProfile>()
            .HasOptional(x => x.OrderTemplate)
            .WithOptionalPrincipal(x => x.OrderProfile);

執行上述操作解決了該問題,但由於某種原因,該問題似乎已經級聯到另一個具有上述循環引用的關系。 此級聯問題涉及訂單 class。 我想這是一個非常令人擔憂的原因,因為這個應用程序在過去 4 年里運行良好,而且這些關系像這樣衰減是令人擔憂的。 有誰知道為什么會這樣?

如果您使用正確的命名約定,EF 將發揮作用。 在此示例中,您不需要流利的 API 來關聯實體。

public partial class Order : ILocationBearingObject
{
    public int Id { get; set; }
    public int? OrderProfileId { get; set; } //means HasOptional (nullable) and ForeignKey

    //variable name must be OrderProfile not Profile
    public virtual OrderProfile OrderProfile { get; set; } 
}

public class OrderProfile
{
    public OrderProfile()
    {
       Orders = new HashSet<Order>();
    }

    public int Id { get; set; }

    //be aware circular reference at any conversion or mapping
    public virtual ICollection<Order> Orders {get; set;} //means WithMany
}

我也有這樣的錯誤。 這是由於 OrderTemplate class 中的 OrderProfileId 屬性與流利的 api model 不匹配引起的

如果我沒記錯的話,您希望 OrderProfile model 是 Order 和 OrderTemplate 之間的多對多關系。 然后,如果是這種情況,請在 OrderProfile 中添加 nvaigation 屬性。

public class OrderProfile 
{
    public int Id { get; set; }
    // other properties

    public virtual ICollection<Order> Orders { get; set; }
    public virtual OrderTemplate OrderTemplate { get; set; }
}

然后把fluent api model改成這樣

// the EF has modelled the relation for normal 1 to many relation
// modelBuilder.Entity<Order>()
//     .HasOptional(x => x.OrderProfile)
//     .WithMany(x => x.Orders)
//     .HasForeignKey(x => x.OrderProfileId);

modelBuilder.Entity<OrderTemplate>()
    .HasOptional(x => x.OrderProfile)
    .WithOptional(x => x.OrderTemplate);

您首先使用數據庫,這總是為實際數據庫 model 和 model EF 從 class 和屬性名稱和映射代碼推斷出的不匹配留出空間。 如果發生這種情況,它可能有助於使 EF 從概念 model 生成數據庫,並查看它在哪里創建它期望的列OrderProfile_Id

這是您在記錄 SQL 語句時將看到的內容:

CREATE TABLE [dbo].[OrderTemplates] (
    [Id] [int] NOT NULL IDENTITY,
    [OrderProfileId] [int],
    [OrderProfile_Id] [int],
    CONSTRAINT [PK_dbo.OrderTemplates] PRIMARY KEY ([Id])
)

...

ALTER TABLE [dbo].[OrderTemplates]
    ADD CONSTRAINT [FK_dbo.OrderTemplates_dbo.OrderProfiles_OrderProfile_Id]
    FOREIGN KEY ([OrderProfile_Id]) REFERENCES [dbo].[OrderProfiles] ([Id])

在那里,您會看到預期的可為空列OrderProfile_Id ,它是OrderProfiles的 FK。 值得注意的是,EF使用OrderProfileId作為外鍵字段。 它只是一個可以用於任何事情的字段。

這是因為 EF6 不支持 1:1 關聯作為外鍵關聯(引用屬性和原始 FK 屬性)。

知道了這一點,補救措施很簡單:刪除屬性OrderTemplate.OrderProfileId並告訴 EF 使用數據庫中的字段OrderTemplate.OrderProfileId

modelBuilder.Entity<OrderProfile>()
    .HasOptional(x => x.OrderTemplate)
    .WithOptionalPrincipal(x => x.OrderProfile)
        .Map(m => m.MapKey("OrderProfileId"));

也就是說,我想知道為什么OrderOrderProfile的外鍵。 它的OrderProfile不是由它的OrderTemplate決定的嗎? 如果它是冗余關系,最好將其刪除。

暫無
暫無

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

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