【发布时间】:2014-12-31 20:45:10
【问题描述】:
我创建了一个 asp.NET MVC Web 应用程序,其中包含两个使用 EF Code First 的模型,它们具有 1 对 0..1 的关系。
public class ClassA
{
public int Id {get;set;}
//other properties
public virtual ClassB ClassB {get;set;}
}
public class ClassB
{
public int Id {get;set;}
//other properties
}
在我的数据库中,这成功地创建了两个表,其中 ClassA 具有 ClassB 的 Nullable FK。这很好用,除了删除 ClassA 记录的情况。在这种情况下,任何关联的 ClassB 记录都会留在数据库中。我知道我可以在 Delete POST 方法中手动删除它们:
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
ClassA classA = context.ClassA.Include(c => c.ClassB).First(c => c.Id == id);
context.ClassB.Remove(classA.ClassB);
context.ClassA.Remove(classA);
context.SaveChanges();
}
我不太喜欢这种方法,因为它依赖于我不会犯错,并假设这种方法是删除记录的唯一方法(有时也可能会针对数据库运行直接 DELETE SQL 语句点)。我在这里创建的示例很简单,但我的实际应用程序涉及大量模型和关联,并且变得相当复杂。虽然我喜欢认为自己是无懈可击的,但我从经验中了解到,我不会也不愿依靠自己来确保记录不会成为孤儿 =)
如何强制数据库强制执行参照完整性,以便在删除 ClassA 时,也删除在该 ClassA 中具有外键的所有 ClassB?
已解决(有点)
按照 Gert 的建议,我使用 Fluent API 来确保将正确的实体设置为 Principle,并将所有关系设置为在删除时级联。不过,我确实遇到了一些问题,主要是因为我的数据库中已经有数据了。幸运的是,我正处于开发阶段,我可以简单地删除所有数据;否则,我不确定如何解决这个问题。
首先我尝试添加 Fluent API 和更新数据库。我收到一个错误,部分内容为:“参数@objname 不明确或声明的@objtype (COLUMN) 错误” 这似乎是由于EF 试图更改现有名称FK 列。在这种情况下,我决定使用 2 个迁移:一个删除现有关系,另一个添加新重新配置的关系。我必须在一系列相当具体的活动中这样做。
- 在我的控制器中注释掉所有对受影响关系的引用,以避免在更新时出错。
-
注释掉模型中的关系。
public class ClassA { public int Id {get;set;} //other properties //public virtual ClassB ClassB {get;set;} } - 添加迁移和更新数据库以删除现有关系。
- 取消注释我在第 1 步和第 2 步中注释掉的所有内容,从而撤消对模型和控制器的所有更改。
-
按照 Gert 的建议在 OnModelCreating 中配置新关系以保存新关系。
modelBuilder.Entity<ClassA>() .HasOptional(b => b.ClassB) .WithRequired() .Map(m => m.MapKey("ClassB_Id")) .WillCascadeOnDelete(); 添加迁移和更新数据库以创建新关系。当我的数据库中有现有数据时,此步骤失败。如果我不能选择简单地清除数据库中的所有数据,我不确定我会如何做到这一点。
【问题讨论】:
标签: c# asp.net-mvc entity-framework relationships