[英]Entity Framework is adding an extra foreign key to my table
I have a very simple data model: a bog standard 1:m relationship. 我有一个非常简单的数据模型:沼泽标准1:m关系。 But I want it slightly denormalised for performance reasons and the EF is not doing what I expect it to do.
但是出于性能原因,我希望它稍微归一化,而EF并没有按照我的预期去做。
I am getting an extra foreign key on a join table when I have a 1:m relationship and also slightly denormalise the data so that my Product
table has a reference to a specific order as well as a list of orders. 当我与1:m关系时,我在联接表上得到了一个额外的外键,并且还对该数据进行了一些非规范化处理,因此我的
Product
表可以引用特定的订单以及订单列表。
Take 2 classes: Customer
and Product
. 分为2类:
Customer
和Product
。 They have am:m relationship, which is to be joined by the Orders
class. 它们具有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; }
}
So far so simple. 到目前为止很简单。 Everything is as I expect it to be with the table definitions:
一切都与我期望的表定义一致:
Customers 顾客
CustomerId int
Name nvarchar(MAX)
Products 制品
ProductId int
Name nvarchar(MAX)
Orders 命令
OrderId int
Customer_CustomerId int
Product_ProductId int
Now the issue. 现在的问题。 For reasons I won't go into right now, I want to hold the latest order for a product on the product table itself, rather than have to query and do a
WHERE OrderId = MAX(OrderId)
on the Orders
table. 由于一些原因,我现在不打算讨论,我想在产品表本身上保留某个产品的最新订单,而不是要在
Orders
表上查询并执行WHERE OrderId = MAX(OrderId)
。
So I change my model class by adding a single line: 因此,我通过添加一行来更改模型类:
public virtual Order MostRecentOrder { get; set; }
The DB definition for the Product
table looks just as I would expect: Product
表的数据库定义看起来与我期望的一样:
MostRecentOrder_OrderId int
However, EF has also added a foreign key to the Orders
table: 但是,EF 还向
Orders
表添加了外键:
Product_ProductId1 int
That shouldn't be there. 那不应该在那里。 Only one
Order
can be the LATEST order, and I have a single instance of the order in my Product
class. 只有一个
Order
可以是最新的Order,而我的Product
类中只有一个Order
实例。
So I tried doing it a bit more explicitly in the Product
class: 因此,我尝试在
Product
类中更明确地做到这一点:
public int MostRecentOrderId { get; set; }
[ForeignKey("MostRecentOrderId")]
public virtual Order MostRecentOrder { get; set; }
The Product
field gets a name change to reflect the explicitly named column in my class, but the Orders
table still has that extra foreign key to the Product
table. “
Product
字段进行了名称更改,以反映我的班级中显式命名的列,但“ Orders
表仍具有该“ Product
表的额外外键。
I kept playing and found that I could get rid of the erroneous foreign key on the Orders
table by unmapping the Product
class: 我一直在玩,发现可以通过取消映射
Product
类来摆脱Orders
表上的错误外键:
public int? MostRecentOrderId { get; set; }
[ForeignKey("MostRecentOrderId")]
[NotMapped]
public virtual Order MostRecentOrder { get; set; }
I also missed the nullable requirement in my prototype ;) 我也错过了原型中的可为空的要求;)
However, now I cannot make use of pre-loading the data. 但是,现在我无法利用预加载数据。
This code: 这段代码:
ApplicationDbContext db = new ApplicationDbContext();
var products = db.Products.Include("Orders").Include("MostRecentOrder").ToList();
throws this exception: 抛出此异常:
A specified Include path is not valid.
指定的包含路径无效。 The EntityType 'WebApplication1.Models.Product' does not declare a navigation property with the name 'MostRecentOrder'.
EntityType'WebApplication1.Models.Product'未声明名称为'MostRecentOrder'的导航属性。
What am I missing here? 我在这里想念什么? I just wish the
Product
table to have a list of orders, and a reference to one (special) order. 我只希望
Product
表具有订单列表, 并引用一个(特殊)订单。 In traditional client/server dev, I would code this SQL to get the data back: 在传统的客户端/服务器开发人员中,我将对此SQL进行编码以获取数据:
-- to go into the "Product" object
SELECT *
FROM Products
LEFT JOIN Orders ON Products.MostRecentOrderId = Orders.OrderId;
WHERE ProductId = 4
and 和
-- to go into the "Product.Orders collection"
SELECT *
FROM Orders
WHERE ProductId = 4;
So, after you add the MostRecentOrder
navigation property, the Product
class would look like this: 因此,在添加
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; }
}
What you can do next is use the Fluent API to configure the relationships inside your context class like this: 接下来,您可以使用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);
}
}
It seems to me that convention based configuration are not explicit enough to tell EF about your relationships in such case. 在我看来,在这种情况下,基于约定的配置还不够明确,无法告诉EF您的关系。 Fluent API is more explicit.
流利的API更明确。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.