C# 如何首先在Entity Framework 6代码中创建多个1:1外键关系?
让我们假设我有三个表,每个表都有一个名为C# 如何首先在Entity Framework 6代码中创建多个1:1外键关系?,c#,entity-framework,ef-code-first,entity-framework-6,one-to-one,C#,Entity Framework,Ef Code First,Entity Framework 6,One To One,让我们假设我有三个表,每个表都有一个名为Id的主键: TableA ------ Id TableB ------ Id TableC ----- Id 目的是让这些实体中的每一个彼此具有一对一的导航属性,以便我可以在给定任何实体的任何方向上导航。不幸的是,我没有找到允许每个实体多次使用的[Key]、[ForeignKey]和导航属性的组合 例如,这是可行的(实体框架认为TableA是1:1关系中的主体): 但这不起作用: public class TableB { [Key]
Id
的主键:
TableA
------
Id
TableB
------
Id
TableC
-----
Id
目的是让这些实体中的每一个彼此具有一对一的导航属性,以便我可以在给定任何实体的任何方向上导航。不幸的是,我没有找到允许每个实体多次使用的[Key]
、[ForeignKey]
和导航属性的组合
例如,这是可行的(实体框架认为TableA
是1:1关系中的主体):
但这不起作用:
public class TableB
{
[Key]
[ForeignKey("TableA,TableC")] // The constructor documentation says this will work, but at runtime it throws an exception
[Required]
public Guid Id { get; set; }
public virtual TableA TableA { get; set; }
public virtual TableC TableC { get; set; }
}
这也不是:
public class TableB
{
[Key]
[Required]
public Guid Id { get; set; }
[ForeignKey("Id")]
public virtual TableA TableA { get; set; }
[ForeignKey("Id")]
public virtual TableC TableC { get; set; }
}
如何使用属性来允许这些关系?目前,如果我想从
TableB
导航到TableC
,我必须在TableA
中导航,这会导致额外的不必要的数据库查找。实体框架似乎想要在可能没有层次关系的地方强制建立层次关系。我认为您需要的是这样一个模型:
public class TableA
{
[Key]
public Guid Id { get; set; }
public virtual TableB TableB { get; set; }
public virtual TableC TableC { get; set; }
}
public class TableB
{
[Key]
[ForeignKey("TableA")]
public Guid Id { get; set; }
public virtual TableA TableA { get; set; }
public virtual TableC TableC { get; set; }
}
public class TableC
{
[Key]
[ForeignKey("TableB")]
public Guid Id { get; set; }
public virtual TableB TableB { get; set; }
[Required]
public virtual TableA TableA { get; set; }
}
您不需要在TableB
实体中为TableC
导航属性指定FK属性,因为TableB
是B和C之间关系的主体
更新
尝试删除Required
数据注释并以这种方式配置关系,覆盖上下文中的OnModelCreating
方法:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<TableA>().HasOptional(a => a.TableC).WithOptionalPrincipal(c => c.TableA);
base.OnModelCreating(modelBuilder);
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity();
基于模型创建(modelBuilder);
}
不幸的是,由于导航属性()上的[必需]
存在错误,我无法使用您的解决方案;但是,我怀疑它会起作用,因为[Required]
建立了关系的主体。这就是为什么在我的示例中,我一直在使用[ForeignKey]
。在微软合并拉请求之前,我似乎被额外的遍历卡住了。不过,我会将您的答案标记为已接受,因为如果没有bug,我怀疑它会起作用。您好@NathanAldenSr,我看不出会向您抛出什么异常,但无论如何,我会用另一种可能的解决方案更新我的答案,希望这有助于您总结错误:尝试保存从数据库加载但未检查其所有[Required]
导航属性的实体将引发一个例外,即导航属性是必需的。这是因为导航属性是延迟加载的,所以在不点击属性的get访问器的情况下,[必需]
注释认为值为null
。您是否尝试了我在更新中共享的配置?它允许您将关系的两端配置为可选。我将尝试一下,谢谢。我通常会尽量避免在模型创建时覆盖,而代之以属性,但在这种情况下,我可能没有选择:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<TableA>().HasOptional(a => a.TableC).WithOptionalPrincipal(c => c.TableA);
base.OnModelCreating(modelBuilder);
}