gpt4 book ai didi

c# - 在 1 对 0..1 关系中对对象删除实现参照完整性

转载 作者:太空宇宙 更新时间:2023-11-03 21:24:55 25 4
gpt4 key购买 nike

我使用 EF Code First 创建了一个带有两个模型的 asp.NET MVC 网络应用程序,它们具有 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 来确保将正确的实体设置为原则,并将所有关系设置为级联删除。不过我确实遇到了一些问题,主要是因为我的数据库中已经有数据了。幸运的是,我正处于开发阶段,我可以简单地删除所有数据;否则,我不确定如何解决这个问题。

首先,我尝试只添加 Fluent API 和更新数据库。我收到一个错误,部分内容为:“参数@objname 不明确或声明的@objtype (COLUMN) 错误” 这似乎是由于 EF 试图更改现有的名称FK专栏。既然如此,我决定使用 2 个迁移:一个用于删除现有关系,另一个用于添加新的重新配置的关系。我必须在一系列相当具体的事件中这样做。

  1. 在我的 Controller 中注释掉所有对受影响关系的引用,以避免在更新时出错。
  2. 注释掉模型中的关系。

    public class ClassA
    {
    public int Id {get;set;}
    //other properties
    //public virtual ClassB ClassB {get;set;}
    }
  3. 添加迁移和更新数据库以删除现有关系。
  4. 通过取消注释我在第 1 步和第 2 步中注释掉的所有内容,取消对模型和 Controller 的所有更改。
  5. 按照 Gert 的建议在 OnModelCreating 中配置新关系以保存新关系。

    modelBuilder.Entity<ClassA>()
    .HasOptional(b => b.ClassB)
    .WithRequired()
    .Map(m => m.MapKey("ClassB_Id"))
    .WillCascadeOnDelete();
  6. Add-Migration 和 Update-Database 创建新关系。当我的数据库中存在现有数据时,此步骤失败。如果我没有简单清除数据库中所有数据的选项,我不确定我将如何完成此操作。

最佳答案

在一对一关联中,您始终必须考虑哪个实体是原则 实体,哪个是从属 实体。依赖者,顾名思义,没有另一个就无法存在。

在你的设计中,原则和依赖是错误的方式:ClassA 是依赖,ClassB 可以独立存在。这就是 EF 恰好解释类模型的方式。如果您希望它以其他方式执行,则必须添加一些映射说明。保持类模型不变,这只能通过流畅的 API 来完成,例如在上下文的 OnModelCreating 覆盖中:

modelBuilder.Entity<ClassA>().HasOptional(a => a.ClassB)
.WithRequired().Map(m => m.MapKey("ClassAId"))
.WillCascadeOnDelete();

现在 ClassB 表中将有一个外键 ClassAId。级联删除确保当 ClassA 被删除时,其依赖的 ClassB 会自动删除。

关于c# - 在 1 对 0..1 关系中对对象删除实现参照完整性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27726175/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com