[英]Entity Framework is adding an extra foreign key to my table
我有一個非常簡單的數據模型:沼澤標准1:m關系。 但是出於性能原因,我希望它稍微歸一化,而EF並沒有按照我的預期去做。
當我與1:m關系時,我在聯接表上得到了一個額外的外鍵,並且還對該數據進行了一些非規范化處理,因此我的Product
表可以引用特定的訂單以及訂單列表。
分為2類: Customer
和Product
。 它們具有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.