我有一个User类,每个用户可以有多个地址。
我还有一个Order类,其中每个订单只能有一个地址。
我有以下代码并且我得到了级联删除错误,在此之前我遇到了外键约束问题并且已经修复了这些错误。
public class User : IdentityUser
{
public virtual ICollection<Purchase> Purchases { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
}
public class Order
{
[Key, ForeignKey("User")]
public string OrderId { get; set; }
public virtual User User { get; set; }
[Required, ForeignKey("Address")]
public int AddressId { get; set; }
public virtual Address Address { get; set; }
public virtual ICollection<OrderItem> Items { get; set; }
}
public class Address
{
public int Id { get; set; }
[Required]
public string UserId { get; set; }
public User User { get; set; }
}
我不确定现在有什么问题,我认为级联问题是我尝试在地址表上实现1-1和1-Many关系。
确切的错误是:
Introducing FOREIGN KEY constraint
'FK_dbo.Purchases_dbo.AspNetUsers_UserId' on table
'Orders' may cause cycles or multiple cascade paths.
Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify
other FOREIGN KEY constraints.
在Visual Studio 2013程序包管理器控制台中执行此语句时出现此错误。
'Update-Package -Force'
修改
在关注@erkaners建议后,我开始重新考虑这个结构。
“用户”可以拥有任意数量的送达地址。我们的一些用户经常发送到多个地址,不应该重复输入这些地址。
'订单'是正在进行的订单,客户选择其先前的地址之一,或在创建此订单时输入新地址。
然后我有一个'OrderHistory'表,它是已完成的订单。
现在我想我实际上并不想删除地址,因为'OrderHistory'表将不再能够引用它的地址了。
相反,我认为我应该添加一个布尔列来标记地址Active / Inactive并完全删除级联删除。这是一个更好的行动方案吗?
答案 0 :(得分:3)
这是因为有两条路径可能导致删除地址。使用流畅的api可以解决这个问题:
public class Order
{
public string OrderId { get; set; }
[Required, ForeignKey("User")]
public string UserId { get; set; }
public virtual User User { get; set; }
[Required, ForeignKey("Address")]
public int AddressId { get; set; }
public virtual Address Address { get; set; }
public virtual ICollection<OrderItem> Items { get; set; }
}
public class Address
{
public int AddressId { get; set; }
[ForeignKey("User")]
public string UserId { get; set; }
public User User { get; set; }
[ForeignKey("Order")]
public string OrderId { get; set; }
public Order Order { get; set; }
}
modelBuilder.Entity<User>()
.HasMany(u => u.Addresses)
.WithRequired(a => a.User)
.HasForeignKey(a => a.UserId);
.WillCascadeOnDelete(false);