gpt4 book ai didi

entity-framework - 在 Entity Framework 中创建没有循环引用的域模型

转载 作者:行者123 更新时间:2023-12-03 20:53:29 26 4
gpt4 key购买 nike

我找到了一个有效的解决方案(使用 DTO 和 AutoMapper),如下所示,但我更喜欢列出解决问题的不同方法和示例的答案,如果收到,这将被标记为答案。

在我的实体模型中,我有一个从子实体到父实体的导航属性。我的项目进展顺利。然后我开始使用AutoFixture进行单元测试,测试失败,AutoFixture说我有一个循环引用。

现在,我意识到像这样的循环引用导航属性在 Entity Framework 中是可以的,但我发现了这篇文章 (Use value of a parent property when creating a complex child in AutoFixture),其中 AutoFixture 的创建者 Mark Seemann 指出:

“作为记录,我已经多年没有编写带有循环引用的 API,因此很有可能避免那些父/子关系。”

所以,我想了解如何重构域模型以避免子/父关系。

下面是有问题的实体类、存储库方法以及我如何使用导致 View 中循环引用的属性。完美的答案将通过示例解释我可以选择的不同选项,以及每种方法的基本优点/缺点。

注意:导致循环引用的属性是 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”

那么,我如何重构域模型以删除循环引用,同时能够轻松地遍历游戏,并执行类似的操作
用户团队.用户.用户名?

最佳答案

我有一个 similar problem不久前使用 AutoFixture 和 EntityFramework。我的解决方案是为 AutoFixture 添加一个扩展,它允许您通过一些递归构建一个 SUT。该扩展最近已在 AutoFixture 中采用。

但我明白你的问题不是关于如何让 AutoFixture 构造递归数据结构,这确实是可能的,而是如何在没有递归的情况下创建域模型。

首先,你有树或图结构。这里除了递归之外的任何东西都意味着通过松散耦合的节点 id 进行间接访问。您不必定义关联,而是必须逐个查询地遍历树或缓存整个事物并通过节点键查找遍历,这取决于树的大小,这可能不切实际。在这里让EF为你做工作非常方便。

另一种常见结构是类似于您的用户/游戏场景的双向导航结构。在这里,将导航流修剪到单个方向通常不是那么不方便。如果您省略一个方向,比如从一场比赛到另一场比赛,您仍然可以轻松地查询所有球队的某一场比赛。所以:用户有一个游戏列表和一个团队列表。团队有游戏列表。游戏也没有导航引用。要获取特定游戏的所有用户,您可以编写如下内容:

var users = (from user in DataContext.Users
from game in user.Games
where game.Name == 'Chess'
select user).Distinct()

关于entity-framework - 在 Entity Framework 中创建没有循环引用的域模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19840537/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com