我有3个实体:Address
,Student
和Faculty
。这是关系图:
实体类:
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
}
public class Faculty
{
public int Id { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
}
public class Address
{
public int Id { get; set; }
public string Street { get; set; }
public Student Student { get; set; }
public Faculty Faculty { get; set; }
}
在我的Context
文件中,我正在定义关系并将级联删除设置为true:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>()
.HasRequired(s => s.Address)
.WithOptional(a => a.Student)
.WillCascadeOnDelete(true);
modelBuilder.Entity<Faculty>()
.HasRequired(s => s.Address)
.WithOptional(a => a.Faculty)
.WillCascadeOnDelete(true);
}
我的用例是,当我删除Student
或Faculty
对象时,我希望同时删除关联的Address
。但是,它以其他方式工作。
对此有何想法/建议?
答案 0 :(得分:2)
真正的问题是你没有正确地模仿你正在寻找的东西。您的学生和教师表之间没有语义差异。因此,假设迁移外键就足够了,你在关系上是不正确的。换句话说,主详细信息表中的主服务器是地址。您的模型显示地址和教师之间存在一对多关系,地址和学生之间存在一对多关系。因此,级联删除工作的唯一方法是首先删除地址。实际上,我可能会将类型添加为子表,以便一个人可以拥有多个地址的多个角色。
我会以不同的方式对其进行建模。我会说PERSON(ID,NAME,TYPE)=&gt; 0,1 ADDRESS(ID,STREET)。在这种情况下,如果您删除某个人(可以是教师或学生),相应的地址也将被删除。
这巧妙地证明了OO和Relational之间的脱节。采用纯OO方法进行数据存储可能会有点奇怪。
答案 1 :(得分:2)
在逻辑上,在什么时候,你想要一个没有人关联的地址吗?你不会。您想为某个人允许多个地址吗?如果没有,那么将所有这些字段打到同一个表中并完成 - 这基本上就是你所说的:你必须同时拥有一个人和一个地址,所以如果你不打算将它们分开,为什么要分开它们?允许多个,或b)允许零?在这种情况下,将它们放在同一个表中是第三范式,并且适用于大多数用途。
答案 2 :(得分:1)
正确的答案是将所有地址列移动到Student / Faculty表中。
然后,为了让EF对您的对象模型感到满意,可以使用Address类的ComplexType属性。
https://msdn.microsoft.com/en-us/data/jj591583.aspx?f=255&MSPPError=-2147217396
我说这是“正确答案”的部分原因&#34;是你还没有解决两个学生共享同一地址记录的问题。您的对象模型中没有任何内容阻止它发生,如果它发生了,那么当您尝试删除一个学生时会发生什么?
答案 3 :(得分:0)
如果您不想更改表架构,则有两种选择:
仅通过存储过程执行删除操作。由于这是存储逻辑,而不是业务逻辑,因此将删除规则封装在过程中是有意义的。
使用ON DELETE触发器。我个人不喜欢以这种方式使用触发器,但这是一种可能性,并允许你继续使用EF不变。