簡體   English   中英

實體框架向我的表添加了一個額外的外鍵

[英]Entity Framework is adding an extra foreign key to my table

我有一個非常簡單的數據模型:沼澤標准1:m關系。 但是出於性能原因,我希望它稍微歸一化,而EF並沒有按照我的預期去做。

當我與1:m關系時,我在聯接表上得到了一個額外的外鍵,並且還對該數據進行了一些非規范化處理,因此我的Product表可以引用特定的訂單以及訂單列表。

分為2類: CustomerProduct 它們具有am:m關系,該關系將由Orders類加入。

public class Customer
{
    public int CustomerId { get; set; }
    public string Name { get; set; }

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

public class Product
{
    public int ProductId { get; set; }
    public string Name { get; set; }

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

public class Order
{
    public int OrderId { get; set; }
    public virtual Customer Customer { get; set; }
    public virtual Product Product { get; set; }
}

到目前為止很簡單。 一切都與我期望的表定義一致:

顧客

CustomerId int
Name nvarchar(MAX)

制品

ProductId int
Name nvarchar(MAX)

命令

OrderId int
Customer_CustomerId int
Product_ProductId int

現在的問題。 由於一些原因,我現在不打算討論,我想在產品表本身上保留某個產品的最新訂單,而不是要在Orders表上查詢並執行WHERE OrderId = MAX(OrderId)

因此,我通過添加一行來更改模型類:

public virtual Order MostRecentOrder { get; set; }

Product表的數據庫定義看起來與我期望的一樣:

MostRecentOrder_OrderId int

但是,EF Orders表添加了外鍵:

Product_ProductId1 int

那不應該在那里。 只有一個Order可以是最新的Order,而我的Product類中只有一個Order實例。

因此,我嘗試在Product類中更明確地做到這一點:

    public int MostRecentOrderId { get; set; }

    [ForeignKey("MostRecentOrderId")]
    public virtual Order MostRecentOrder { get; set; }

Product字段進行了名稱更改,以反映我的班級中顯式命名的列,但“ Orders表仍具有該“ Product表的額外外鍵。

我一直在玩,發現可以通過取消映射Product類來擺脫Orders表上的錯誤外鍵:

    public int? MostRecentOrderId { get; set; }

    [ForeignKey("MostRecentOrderId")]
    [NotMapped]
    public virtual Order MostRecentOrder { get; set; }

我也錯過了原型中的可為空的要求;)

但是,現在我無法利用預加載數據。

這段代碼:

ApplicationDbContext db = new ApplicationDbContext();
var products = db.Products.Include("Orders").Include("MostRecentOrder").ToList();

拋出此異常:

指定的包含路徑無效。 EntityType'WebApplication1.Models.Product'未聲明名稱為'MostRecentOrder'的導航屬性。

我在這里想念什么? 我只希望Product表具有訂單列表, 引用一個(特殊)訂單。 在傳統的客戶端/服務器開發人員中,我將對此SQL進行編碼以獲取數據:

-- to go into the "Product" object
SELECT * 
FROM Products
LEFT JOIN Orders ON Products.MostRecentOrderId = Orders.OrderId;
WHERE ProductId = 4

-- to go into the "Product.Orders collection"
SELECT * 
FROM Orders 
WHERE ProductId = 4;

因此,在添加MostRecentOrder導航屬性之后, Product類將如下所示:

public class Product
{
    public int ProductId { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Order> Orders { get; set; }
    public virtual Order MostRecentOrder { get; set; }
}

接下來,您可以使用Fluent API在上下文類中配置關系,如下所示:

public class Context : DbContext
{
    public DbSet<Order> Orders { get; set; }
    public DbSet<Product> Products { get; set; }
    public DbSet<Customer> Customers { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder
            .Entity<Order>()
            .HasRequired(x => x.Product)
            .WithMany(x => x.Orders);

        modelBuilder
            .Entity<Product>()
            .HasOptional(x => x.MostRecentOrder);
    }
}

在我看來,在這種情況下,基於約定的配置還不夠明確,無法告訴EF您的關系。 流利的API更明確。

暫無
暫無

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

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