gpt4 book ai didi

entity-framework - 为什么我必须手动提供外键属性值(在这种情况下)?

转载 作者:行者123 更新时间:2023-12-04 23:53:59 25 4
gpt4 key购买 nike

当我有这样的模型时......

public class Order
{
[Key, Column(Order = 1)]
public int CustomerId { get; set; }
[Key, Column(Order = 2)]
public int OrderId { get; set; }

public ICollection<OrderItem> Items { get; set; }
}

public class OrderItem
{
[Key, Column(Order = 1)]
public int CustomerId { get; set; }
[Key, Column(Order = 2)]
public int OrderId { get; set; }
[Key, Column(Order = 3)]
public int OrderItemId { get; set; }
}

...我不需要提供外键值 OrderItem.CustomerIdOrderItem.OrderId当我添加 Order - OrderItems 时手动图表到数据库:

var order = new Order
{
CustomerId = 5,
OrderId = 1,
Items = new List<OrderItem>
{
// I don't need to set CustomerId and OrderId here
new OrderItem { OrderItemId = 12 }
}
};
context.Orders.Add(order);
context.SaveChanges();

SaveChanges将生成 SQL 语句以插入 OrderOrderItem .对于 OrderItem它是:

exec sp_executesql N'insert
[dbo].[OrderItems]([CustomerId], [OrderId], [OrderItemId])
values (@0, @1, @2)
',N'@0 int,@1 int,@2 int',@0=5,@1=1,@2=12

所以,FKs CustomerIdOrderId设置正确( @0=5@1=1 )。

但是,如果我将另一个关系添加到 Customer通过向 Order 添加导航属性将实体添加到模型中...

public Customer Customer { get; set; }

...带有 Customer像这样上课...

public class Customer
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CustomerId { get; set; }
}

...并调用与上面相同的代码(假设 CustomerCustomerId = 5 存在于数据库中)我得到以下 SQL:

exec sp_executesql N'insert
[dbo].[OrderItems]([CustomerId], [OrderId], [OrderItemId])
values (@0, @1, @2)
',N'@0 int,@1 int,@2 int',@0=0,@1=1,@2=12

几乎相同,但 CustomerId0在这种情况下 ( @0=0 ) 导致 Order - OrderItem 的外键约束违规关系。如果 CustomerCustomerId = 0会存在并且这个客户有一个 OrderOrderId = 1 , 不会发生异常并且 OrderItem会被添加到错误的订单中,这可能比异常更糟糕。

可以通过设置 CustomerId 来解决这个问题。 (这是 FK 的一部分)在新的 OrderItem 中:

Items = new List<OrderItem>
{
// I don't need to set OrderId here, BUT CustomerId
new OrderItem { CustomerId = 5, OrderItemId = 12 }
}

或者 - 它可以通过附加客户 ID 5 来修复到上下文(我不知道为什么它会起作用)。

是否有合理的解释为什么我必须手动提供 FK(或本示例中的部分 FK)或者这是一个错误?

(我为此模型使用了 EF 5.0 和 .NET 4.0。)

最佳答案

我觉得你的模型很奇怪,我怀疑是你的困惑。

根据我所看到的情况,我猜您的客户可以有很多订单,每个订单应该只有一种 OrderItem 类型,但可以有很多 OrderItem。一个订单不能属于多个客户。一个 OrderItem 可以属于多个 Order。

如果这是真的,那么我认为您需要一个类似的模型;

public class Customer
{
//Is the key by naming convention or you could use [Key]
public Guid CustomerId { get; set; }
public ICollection<Order> Orders { get; set; }
}
public class Order
{
//Is the key by naming convention or you could use [Key]
public Guid OrderId { get; set; }
public Guid CustomerId { get; set; } //This doesn't need to be part of the key
public Customer Customer { get; set; }
public ICollection<OrderItem> OrderItems { get; set; }
}
public class OrderItem
{
[Key, Column(Order = 0)]
public Guid OrderItemId { get; set; }
[Key, Column(Order=1)]
public Guid OrderId { get; set; }
public ICollection<Order> Orders { get; set; }
}

然后,当您需要查询是否需要了解 Customer 的 OrderItems 时,您可以使用 Include 或数据投影(如

OrderItems.Select(x=>new { 
CustomerId = x.Order.Customer.Id,
//this rest of your properties
});

或者如果你想要整个实体

  OrderItems.Include(x=>x.Order.Customer)

关于entity-framework - 为什么我必须手动提供外键属性值(在这种情况下)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14553999/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com