Entity framework 实体框架代码第一对一必需关系

Entity framework 实体框架代码第一对一必需关系,entity-framework,Entity Framework,当使用实体框架代码First 4.3.1时,可以创建多重性为1:1的关系。也就是说,关系两端各有一个实体 可以将1对1关系配置为必需或必需可选^。但是,当我在两者之间切换时,我看不到以下方面的任何差异: 已生成数据库架构。我的目标是SQL Server 2008 EF的运行时行为 因此,我能够创建一个RequiredPrincipalAs记录,而不需要相应的RequiredDependentAs记录,尽管关系被配置为required。这似乎与HasRequired(…)的文档相矛盾: 从该实

当使用实体框架代码First 4.3.1时,可以创建多重性为1:1的关系。也就是说,关系两端各有一个实体

可以将1对1关系配置为必需必需可选^。但是,当我在两者之间切换时,我看不到以下方面的任何差异:

  • 已生成数据库架构。我的目标是SQL Server 2008
  • EF的运行时行为
因此,我能够创建一个RequiredPrincipalAs记录,而不需要相应的RequiredDependentAs记录,尽管关系被配置为required。这似乎与HasRequired(…)的文档相矛盾:

从该实体类型配置所需的关系。除非指定此关系,否则无法将实体类型的实例保存到数据库中。数据库中的外键将不可为空

所需的关系实体:

public class RequiredPrincipalA
{
    public int Id { get; set; }
    public virtual RequiredDependentA DependentA { get; set; }
}

public class RequiredDependentA
{
    public int Id { get; set; }
    public virtual RequiredPrincipalA PrincipalA { get; set; }
}
public class RequiredPrincipalB
{
    public int Id { get; set; }
    public virtual OptionalDependentB DependentB { get; set; }
}

public class OptionalDependentB
{
    public int Id { get; set; }
    public virtual RequiredPrincipalB PrincipalB { get; set; }
}
必需的可选关系实体:

public class RequiredPrincipalA
{
    public int Id { get; set; }
    public virtual RequiredDependentA DependentA { get; set; }
}

public class RequiredDependentA
{
    public int Id { get; set; }
    public virtual RequiredPrincipalA PrincipalA { get; set; }
}
public class RequiredPrincipalB
{
    public int Id { get; set; }
    public virtual OptionalDependentB DependentB { get; set; }
}

public class OptionalDependentB
{
    public int Id { get; set; }
    public virtual RequiredPrincipalB PrincipalB { get; set; }
}
DbContext和模型配置:

public class AppContext : DbContext
{
    public DbSet<RequiredPrincipalA> PrincipalAs { get; set; }
    public DbSet<RequiredDependentA> DependentAs { get; set; }

    public DbSet<RequiredPrincipalB> PrincipalBs { get; set; }
    public DbSet<OptionalDependentB> DependentBs { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<RequiredPrincipalA>()
            .HasRequired(o => o.DependentA)
            .WithRequiredPrincipal(o => o.PrincipalA);

        modelBuilder.Entity<RequiredPrincipalB>()
            .HasOptional(o => o.DependentB)
            .WithRequired(o => o.PrincipalB);
    }
}
公共类AppContext:DbContext
{
公共数据库集{get;set;}
公共DbSet依赖项{get;set;}
公共DbSet PrincipalBs{get;set;}
公共DbSet DependentBs{get;set;}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity()
.HasRequired(o=>o.DependentA)
.具有所需的委托人(o=>o.PrincipalA);
modelBuilder.Entity()
.has可选(o=>o.DependentB)
.需要(o=>o.PrincipalB);
}
}
测试代码:

Database.SetInitializer(new DropCreateDatabaseAlways<AppContext>());

using (var ctx = new AppContext())
{
    ctx.Database.Initialize(force: false);

    ctx.PrincipalAs.Add(new RequiredPrincipalA());
    ctx.PrincipalBs.Add(new RequiredPrincipalB());

    ctx.SaveChanges();
}
Database.SetInitializer(新的DropCreateDatabaseAlways());
使用(var ctx=new AppContext())
{
ctx.Database.Initialize(强制:false);
添加(新的RequiredPrincipalA());
添加(新的RequiredPrincipalB());
ctx.SaveChanges();
}
我知道我可以在RequiredPrincipalA.DependentARequiredDependentA.PrincipalA的导航属性中添加[必需]数据属性。这将导致EF验证阻止上述情况。但是,我不想这样做,因为它还验证了在更新现有实体时填充的导航属性。这意味着应用程序必须为每次更新预取关系另一端的实体

为什么仅仅在更改必需的必需的之间的关系时,我看不到EF行为的任何差异


^请注意,可选选项也受支持,但这并不构成我问题的一部分。配置可选关系时,生成的数据库架构和运行时行为存在明显差异。

我不知道为什么在这种情况下允许使用required,但它不能存在于数据库中,因为关系是基于主键构建的。Required Required表示如果相关B不存在,则无法插入A;如果相关A不存在,则无法插入B=>既不能插入A也不能插入B

数据库关系始终具有主体,并且依赖实体-主体可以始终存在,而不存在依赖关系


只有当A和B都映射到同一个表()时,才能实现EF中所需的Real required,因为在这种情况下,它们都是通过单个insert命令插入的。

这不是一个真正的答案,但我有更多的话要说,而不是在注释中。但你知道,我写了900页的书……这就是我的写作方式。:)

奇怪的是,我期望fluent配置与数据注释的行为方式相同,但我很困惑它没有这样做。(我用这个线程的链接ping了Rowan Miller以获得他的反馈。)我的意思是:在保存更改期间验证约束

在数据库方面,我支持Ladislav。在模型中,EF使用相关实体的键定义了1:1。但是在数据库中,不能在两个表中都有FKs,因此只有数据库中的依赖表需要该约束,即它的PK映射到主表中的现有PK


最后,我理解你不希望EF强制执行关系的原因,如果你不打算总是处理完整的图形。我认为1:1关系是EF关系映射中最令人困惑的一种,我总是发现自己不得不回去寻找规则和工作方式的提醒

老问题。但由于EF6仍然在使用,甚至可以用于.Net标准,而且这个问题可能会非常讨厌,我认为值得一提的是,我在其他答案中找不到这一点

的确,
HasRequired-WithRequired-principal
HasRequired-WithRequired
都会产生相同的数据库模式和运行时行为。也就是说,使用这两种映射,可以在不使用依赖实体的情况下保存主体,并在以后删除依赖实体。
所需的内容到此为止

但有一种方法可以让EF在创建实体时验证所需的关系,这就是简单地添加一个
[必需]
属性:

需要公共类Principala
{
公共int Id{get;set;}

[必需]//谢谢你的回答。这肯定澄清了我问题的数据库架构方面。但是,我非常想理解为什么EF中没有任何明显的行为变化。是否允许required,因为它可以由EF在运行时强制执行,即使实际上不可能在SQL中强制执行此约束?Lu现在,在配置r/r和r/o时,架构没有什么不同