我转载了一个关于实体框架问题的简单示例。
我想拥有三个表:
Users, Projects, WorkOrders
表Users
包含有关所有其他表(示例中只有两个)的用户的信息。 WorkOrders
拥有有关必须在此工作单上进行工作的User
以及它属于哪个Project
的信息。
以下是课程:
public class User
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<WorkOrder> WorkOrders { get; set; }
public virtual ICollection<Project> Projects { get; set; }
}
public class Project
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int ManagerId { get; set; }
public DateTime Start { get; set; }
public virtual User Manager { get; set; }
public virtual ICollection<WorkOrder> WorkOrders { get; set; }
}
public class WorkOrder
{
[Key]
public int Id { get; set; }
public int Number { get; set; }
public string Type { get; set; }
public int AssigneeId { get; set; }
public int ProjectId { get; set; }
public virtual Project Project { get; set; }
public virtual User Assignee { get; set; }
}
当我尝试运行程序时,它会引发异常:
'在表'WorkOrders'上引入FOREIGN KEY约束'FK_dbo.WorkOrders_dbo.Projects_ProjectId'可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束。
然后我走了另一条路。我尝试使用EF进行数据库优先的方法。我首先在SQL Server Management Studio中创建了表和连接:
然后,使用代码优先方法,EF生成的模型与我的模型几乎相同。
public partial class User
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public User()
{
this.Project = new HashSet<Project>();
this.WorkOrder = new HashSet<WorkOrder>();
}
public int Id { get; set; }
public string Name { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Project> Project { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<WorkOrder> WorkOrder { get; set; }
}
public partial class Project
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Project()
{
this.WorkOrder = new HashSet<WorkOrder>();
}
public int Id { get; set; }
public string Name { get; set; }
public int ManagerId { get; set; }
public System.DateTime Start { get; set; }
public virtual User User { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<WorkOrder> WorkOrder { get; set; }
}
public partial class WorkOrder
{
public int Id { get; set; }
public int Number { get; set; }
public string Type { get; set; }
public int AssigneeId { get; set; }
public int ProjectId { get; set; }
public virtual Project Project { get; set; }
public virtual User User { get; set; }
}
因此,除了SuppressMesages
和WorkOrder
类中的User
和构造函数以外,代码几乎完全相同。第二种方法可行。
我想知道,有什么区别?上下文类也和我自己的一样。该FK约束或级联删除设置在何处或如何定义?
答案 0 :(得分:1)
不幸的是,首先使用删除级联创建FK的EF代码的默认行为。因此,在定义关系时,您只需更改此设置即可:
//in context
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Entity<Project>()
.HasRequired<User>(s => s.User)
.WithMany()
.WillCascadeOnDelete(false);
如果您只想更改所有FK的行为,则modelBuilder.Conventions
中可能也有约定。