代码首先导致所需的关系是可选的?

public class Client { public Int32 ClientID { get; set; } public virtual ICollection InquiryManufacturers { get; set; } public virtual ICollection Products { get; set; } public virtual ICollection InquiryRetailers { get; set; } } public class Product { public Int32 ProductID { get; set; } public Int32 ClientID { get; set; } public virtual Client Client { get; set; } public virtual ICollection Inquiries { get; set; } } public class Inquiry { public Int32 InquiryID { get; set; } public Int32 ProductID { get; set; } public Int32 ManufacturerID { get; set; } public Int32 RetailerID { get; set; } public virtual Product Product { get; set; } public virtual Client Manufacturer { get; set; } public virtual Client Retailer { get; set; } } 

流利的Api是

 HasRequired(i => i.Product) .WithMany(p => p.Inquiries); HasRequired(i => i.Manufacturer) .WithMany(p => p.InquiryManufacturers) .HasForeignKey(p => p.ManufacturerID); HasRequired(i => i.Retailer) .WithMany(p => p.InquiryRetailers) .HasForeignKey(p => p.RetailerID); 

所以这里有一些我定义的类。 他们的关系如下:客户和产品有一对多,客户和查询有一对多,产品和查询有一对多。 我在这里使用Code First。 现在使用流畅的api我已经定义了关系,这些关系应该是必需的,这意味着客户端和产品关系不能为空,客户端和查询也不能为空。

但是,Client&Inquiry之间的关系被强制为Code First的可选关系。 当我尝试使它们成为必需时,EF不会生成数据库。

有人能告诉我我的模型有什么问题导致EF不能在Client和Inruiry之间建立必要的关系吗? 这是由于级联删除吗? 当我读到一些mssql在Client,Product和Inquiry之间只能有一个级联删除路径时。 任何帮助解释都会很好。

EF Code First默认情况下在生成的外键约束上将cascade delete设置为true。 而且因为你只能有一个级联路径,你会得到一个像这样的exception:

“在表”查询’中引入FOREIGN KEY约束’Inquiry_Retailer’可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束。

在您的模型中,您有3个从客户端到查询的级联路径:

客户咨询零售商 – > 查询
客户咨询制造商 – > 查询
客户 – 产品 – > 产品咨询 – > 查询

所以你需要设置WillCascadeOnDelete(false)至少两个关系(取决于你的要求):

 modelBuilder.Entity().HasRequired(i => i.Product) .WithMany(p => p.Inquiries); modelBuilder.Entity().HasRequired(i => i.Manufacturer) .WithMany(p => p.InquiryManufacturers) .HasForeignKey(p => p.ManufacturerID).WillCascadeOnDelete(false); modelBuilder.Entity().HasRequired(i => i.Retailer) .WithMany(p => p.InquiryRetailers) .HasForeignKey(p => p.RetailerID).WillCascadeOnDelete(false);