3

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

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.CustomerId,我不需要手动提供外键值:OrderItem.OrderIdOrder - 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

因此,FKCustomerIdOrderId正确设置(@0=5@1=1)。

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

public Customer Customer { get; set; }

......Customer像这样的课程......

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

...并调用与上面相同的代码(假设数据库中存在Customerwith CustomerId= 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。如果存在Customerwith CustomerId=0并且该客户有Orderwith OrderId= 1,则不会发生异常,并且OrderItem将被添加到可能比异常更糟糕的错误订单中。

可以通过在 new 中设置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。)

4

1 回答 1

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; }
    }

然后,当您需要查询是否需要按客户了解 OrderItems 时,您可以使用 Include 或使用数据投影来执行此操作,例如

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

或者如果你想要整个实体

  OrderItems.Include(x=>x.Order.Customer)
于 2013-02-20T01:58:49.523 回答