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