Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.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# 将具有多个引用的实体映射到同一类型_C#_.net_Entity Framework - Fatal编程技术网

C# 将具有多个引用的实体映射到同一类型

C# 将具有多个引用的实体映射到同一类型,c#,.net,entity-framework,C#,.net,Entity Framework,例如,项目有对用户的引用(1个可选,1个必需): public class Project { public User RequiredUser { get; set; } public User OptionalUser { get; set; } } 而用户有许多项目: public class User { public ICollection<Project> Projects { get; set; } } 公共类用户{ 公共ICollectio

例如,
项目
有对
用户的引用(1个可选,1个必需):

public class Project {
    public User RequiredUser { get; set; }
    public User OptionalUser { get; set; }
}
用户
有许多项目:

public class User {
    public ICollection<Project> Projects { get; set; }
}
公共类用户{
公共ICollection项目{get;set;}
}
这样配置是否正确:

modelBuilder.Entity<User>()
    .HasMany(i => i.Projects)
    .WithRequired(i => i.RequiredUser);

modelBuilder.Entity<Project>().HasOptional(i => i.OptionalUser);
modelBuilder.Entity()
.HasMany(i=>i.Projects)
.WithRequired(i=>i.RequiredUser);
modelBuilder.Entity().has可选(i=>i.OptionalUser);

这似乎是循环引用()的一种情况,并且肯定会成为一种糟糕的设计。考虑一下为什么需要在
项目中引用
用户
,而该用户已经在
用户
中。在这里查看更多信息:

我认为您的代码可以工作,但不是您期望的方式:
i收集项目
将仅包含
项目
实例,其中
用户
所需用户

我个人会使用带有
IsRequired
标志的中间表来映射这两个实体,但这会稍微改变行为,并引入一种不太容易处理的
多对多
关系:

public class Project {
    public ICollection<ProjectUser> Users { get; set; }
}

public class ProjectUser {
    public Project Project { get; set; }
    public User User { get; set; }
    public bool IsRequired { get; set; }
}

public class User {
    public ICollection<ProjectUser> Projects { get; set; }
}
公共类项目{
公共ICollection用户{get;set;}
}
公共类项目用户{
公共项目{get;set;}
公共用户{get;set;}
需要公共布尔值{get;set;}
}
公共类用户{
公共ICollection项目{get;set;}
}
优点是,您可以在一个项目中拥有更多的“可选用户”(或必需用户),但如果您的需求是只拥有一个(必需的)用户,那么您需要注意业务逻辑中的这一限制。如果您有两种以上可能的“映射类型”,例如,
Owner
Developer
Tester
,则也可以使用枚举替换
bool


注意:如果你没有利用这一优势,你最好使用Flater的答案。

根据经验,如果你建立了单独的关系(
RequiredUser
/
OptionalUser
),你的
用户
类中还需要单独的
IEnumerable
属性

public class User {
    public ICollection<Project> Projects_Required { get; set; }
    public ICollection<Project> Projects_Optional { get; set; }
}
公共类用户{
公共ICollection项目\u必需{get;set;}
公共ICollection项目\u可选{get;set;}
}
然后,您的设置将变为:

modelBuilder.Entity<User>()
    .HasMany(i => i.Projects_Required)
    .WithRequired(i => i.RequiredUser);

 modelBuilder.Entity<User>()
    .HasMany(i => i.Projects_Optional)
    .WithOptional(i => i.OptionalUser);
modelBuilder.Entity()
.HasMany(i=>i.Projects\u必需)
.WithRequired(i=>i.RequiredUser);
modelBuilder.Entity()
.HasMany(i=>i.Projects\u可选)
.with可选(i=>i.OptionalUser);
然后,如果您选择,您可以添加一个结合这两个列表的
AllProjects
自定义属性。然而,这似乎是一件危险的事情,因为您需要将这些列表分开,因为它们处理的是不同的关系。为了避免混淆,我会尽量把它们分开


如果有一种方法可以设置EF,使两个关系在同一个列表属性中结束,那么我还没有找到它。实施起来似乎既困难又危险。

假设可选用户是一个辅助用户,在第一个用户生病的情况下负责项目。我不知道OP的实际用例是什么,但是在一些场景中,创建双重关系可以按预期工作。如果添加了多个实体,它们应该打包在列表/数组/ienumerable中,这并不总是正确的。如果您需要能够将多个实体分开,那么不同的属性似乎可以。其次,大多数EF类都有相互关联的实体,因此您可以从任意方向进行遍历。我认为没有理由在这里假设循环引用问题。这将需要额外的业务逻辑来确保每个问题只存在一个。这似乎与原始代码的意图背道而驰,因为它现在允许每个代码的倍数。它还引入了一个多对多的关系,其中一个不是直接需要的,我建议不要添加,除非你需要它。@Flater:只是在我的答案末尾添加了一个注释。根据他的具体业务案例,这可能是更好的方法。@Flater:
它还引入了一种多对多关系,其中不直接需要一对多关系,我建议不要添加这种关系
-你能解释一下为什么不建议使用
多对多
?如果需要一对多关系,使用添加的业务逻辑实现多对多似乎是多余的,这样可以确保每个业务逻辑只添加一个。如果RequiredUser和OptionalUser在功能上不同(例如,一个地址是项目经理,另一个地址是联系人),将它们放在同一个IEnumerable上会在将来的实现中引入许多可能的错误。我很可能是OP把这个问题的属性名称改成了简单的名称。好的,明白了。这一点我同意。正如我所说的,如果这是他的业务案例,那么你的解决方案会更好,但是如果是,例如,像你对Kangkan的评论中那样,那么多个“可选用户”可能是一个可能的用例……好的。这是有道理的。考虑<代码>用户<代码>他已经打开的项目和他被指定开发的项目。如果两个用户在功能上不同(项目创建者VS项目开发人员),如果你把它们看作是项目的两个不同属性,它会变得容易很多;并作为用户的不同项目。