【发布时间】:2013-11-07 15:56:37
【问题描述】:
我找到了一个可行的解决方案(使用 DTO 和 AutoMapper),如下所示,但我更喜欢列出解决问题的不同方法的答案以及示例如果收到将被标记为答案。
在我的实体模型中,我有一个从子实体到父实体的导航属性。我的项目进展顺利。然后我开始用 AutoFixture 进行单元测试,测试失败,AutoFixture 说我有循环引用。
现在,我意识到像这样的循环引用导航属性在 Entity Framework 中是可以的,但我发现了这篇文章 (Use value of a parent property when creating a complex child in AutoFixture),其中 AutoFixture 的创建者 Mark Seemann 指出:
“作为记录,我已经很多年没有写过一个带有循环引用的 API,所以很可能避免那些父/子关系。”
所以,我想了解如何重构域模型以避免子/父关系。
以下是有问题的实体类、存储库方法,以及我如何使用导致视图中循环引用的属性。 完美的答案将通过示例解释我可以从中选择的不同选项,以及每种方法的基本优缺点。
注意:导致循环引用的属性是 User,在 UserTeam 模型中。
型号:
public class UserProfile
{
public UserProfile()
{
UserTeams = new HashSet<UserTeam>();
Games = new HashSet<Game>();
}
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public virtual ICollection<UserTeam> UserTeams { get; set; }
public virtual ICollection<Game> Games { get; set; }
}
public class Game
{
public Game()
{
UserTeams = new HashSet<UserTeam>();
}
public int Id { get; set; }
public int CreatorId { get; set; }
public virtual ICollection<UserTeam> UserTeams { get; set; }
}
public class UserTeam
{
public UserTeam()
{
UserTeam_Players = new HashSet<UserTeam_Player>();
}
public int Id { get; set; }
public int UserId { get; set; }
public int GameId { get; set; }
public virtual UserProfile User { get; set; }
public virtual ICollection<UserTeam_Player> UserTeam_Players { get; set; }
}
存储库方法
public IEnumerable<Game> GetAllGames()
{
using (DataContext)
{
var _games = DataContext.Games
.Include(x => x.UserTeams)
.Include(x => x.UserTeams.Select(y => y.User))
.ToList();
if (_games == null)
{
// log error
return null;
}
return _games;
}
}
查看
@model IEnumerable<Game>
@foreach (var item in Model){
foreach (var userteam in item.UserTeams){
<p>@userteam.User.UserName</p>
}
}
现在,如果我删除“用户”导航属性,我将无法执行“@userteam.User.UserName”
那么,我如何重构域模型以删除循环引用,同时能够轻松地循环游戏,并执行类似的操作 用户团队.用户.用户名?
【问题讨论】:
-
我认为这里有一些上下文。当我说“我已经很多年没有写过带有循环引用的 API”时,我忘了说我也很多年没有使用过 ORM(如实体框架)。
-
@MarkSeemann - 啊。 :)
-
FWIW,在任何 ORM 中具有双向导航属性违反了 Aggregate Root 模式。虽然没有人说您必须使用聚合根,但Domain-Driven Design 解释了聚合根是什么以及您应该关心的原因。简而言之,由于双向导航属性,不清楚哪个数据结构是关联数据的权威所有者。
-
@MarkSeemann “...我也有好几年没有使用 ORM(如 [EF])...” - 对于我们好奇的以 Microsoft 为中心的人来说,有什么 i> 你一直在使用它来回避这些问题?
-
@Lumirris 文件/blob,主要是...和 Simple.Data,如果我必须与 RDBMS 对话。
标签: entity-framework autofixture