Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在Entity Framework Core中建立多个一对一关系?_C#_One To One_Ef Core 3.0 - Fatal编程技术网

C# 如何在Entity Framework Core中建立多个一对一关系?

C# 如何在Entity Framework Core中建立多个一对一关系?,c#,one-to-one,ef-core-3.0,C#,One To One,Ef Core 3.0,我有两个实体,分别是父,和子;每个父级最多可以有两个子级引用。我已按如下方式设立了我的实体: 类父类 { [关键] public int ParentId{get;set;} public int PrimaryChildId{get;set;} 公共子PrimaryChild{get;set;} public int SecondaryChildId{get;set;} 公共子项?第二个子项{get;set;} //剩余财产 } 班童 { [关键] public int ChildId{get

我有两个实体,分别是
,和
;每个父级最多可以有两个子级引用。我已按如下方式设立了我的实体:

类父类
{
[关键]
public int ParentId{get;set;}
public int PrimaryChildId{get;set;}
公共子PrimaryChild{get;set;}
public int SecondaryChildId{get;set;}
公共子项?第二个子项{get;set;}
//剩余财产
}
班童
{
[关键]
public int ChildId{get;set;}
public int ParentId{get;set;}
公共父级{get;set;}
//剩余子属性
}
DbContext.OnModelCreating
中,我有以下代码:

模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
实体(生成器=>
{
builder.HasOne(p=>p.PrimaryChild);
builder.HasOne(p=>p.SecondaryChild);
});
}
这还不足以实现我在这里想要实现的目标。我得到一个错误:

无法确定“父”类型的导航属性“Child.Parent”表示的关系。手动配置关系,或使用“[NotMapped]”属性或使用“OnModelCreating”中的“EntityTypeBuilder.ignore”忽略此属性

我试图从
子实体
设置关系,但我得到了不同的错误,因为这使我为同一属性设置了两个关系。我不想在我的孩子身上有两个导航属性,因为我知道一次只能使用一个,因为这会导致模型混乱


我曾在互联网上搜索过一点,但我没有找到以这种方式建立的关系。

过去几天我一直在尝试类似的方法,在尝试了各种数据注释和流畅的API之后,我能想出的最干净的解决方案是非常简单的,两者都不需要。它只需要在父类中添加一个“private”构造函数(如果使用延迟加载,则添加一个“protected”构造函数),将“DbContext”对象注入父类。只需将“Parent”和“Child”类设置为普通的一对多关系,现在可以从“Parent”实体中使用数据库上下文,您可以使用Find()方法使“PrimaryChild”和“SecondaryChild”简单地从数据库返回查询。Find()方法还使用缓存,因此如果多次调用getter,它将只访问数据库一次

以下是有关此能力的文档:

注意:“PrimaryChild”和“SecondaryChild”属性是只读的。要修改它们,请设置“PrimaryChildId”和“SecondaryChildId”属性

class Parent
{
    public Parent() { }
    private MyDbContext Context { get; set; }
    // make the following constructor 'protected' if you're using Lazy Loading
    private Parent(MyDbContext Context) { this.Context = Context; }

    [Key]
    public int ParentId { get; set; }
    public int PrimaryChildId { get; set; }
    public Child PrimaryChild { get { return Context.Children.Find(PrimaryChildId); } }
    public int? SecondaryChildId { get; set; }
    public Child SecondaryChild { get { return Context.Children.Find(SecondaryChildId); } }
    // remaining properties
}

class Child
{
    [Key]
    public int ChildId { get; set; }
    public int ParentId { get; set; }
    public Parent Parent { get; set; }
    // remaining child properties 
}

我认为用一对多比较好。因为你有一个父母和很多孩子。从理论上讲,一对一是不好的。EF如何知道哪个孩子是主要的,哪个是次要的?我认为你在这里有一种多对一的关系。您可以在域逻辑中实施自己的规则。您可以创建自己的
PrimaryChild
属性来获取集合中的第一个孩子或类似的东西。@Anton,是的,我开始这么想。我总是可以在业务层强制执行限制,这样,如果需求发生变化,将来会变得更容易。我有点好奇这是否可能,所以我想我会让这个问题保持活跃。谢谢你的意见。同意@chadnt。当我设计这个时,我只考虑了业务需求,如果我手动完成所有的数据库管理,这当然可以完成,但我认为不值得为此放弃ORM的功能。@Jesse good。我做了一个头脑风暴:)我的需求已经改变,我甚至没有这个设置了,但这是一个相当巧妙的解决方案。我接受了这个答案,因为那肯定对我有用。