我找到了一个可行的解决方案(使用DTOS和AUTOMAPPER),该解决方案在下面复制,但我更喜欢一个答案来列出 解决问题的方法 用示例,如果收到的话,这将被标记为答案。

在我的实体模型中,我有一个从子实体到父母实体的导航属性。我的项目正在游泳。然后,我开始使用自动固定来进行单元测试,并且测试失败,自动futotuture说我有圆形参考。

现在,我意识到像这样的圆形参考导航属性在实体框架内是可以的,但是我发现了这篇文章(在Autofuture中创建复杂的孩子时,请使用父属性的价值),自动Fofture的创建者Mark Seemann所说:

“作为记录,我已经有多年的圆形参考文献了,因此很有可能避免那些父母/子女关系。”

因此,我想了解如何对域模型进行重构以避免孩子/父母的关系。

以下是所讨论的实体类,存储库方法,以及我如何使用属性引起循环参考的属性。 完美的答案将解释我可以选择的不同选择,以及每种方法的基本利弊。

注意:引起循环参考的属性是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'

那么,如何重构域模型以删除圆形参考,同时能够轻松地循环通过游戏,并执行userteam.user.username之类的操作?

有帮助吗?

解决方案

我曾有一个 类似的问题 不久前使用自动框架和实体框架。我的解决方案是在自动倒装置中添加扩展名,使您可以使用一些递归构建SUT。该扩展最近已在自动框架中采用。

但是我知道您的问题不是关于如何使自动固定构建递归数据结构的问题,这确实是可能的,而是如何在没有递归的情况下创建域模型。

首先,您有树或图形结构。除递归外,其他任何东西都意味着通过松散的耦合节点ID间接。您不必定义关联,而是必须逐渐浏览树木查询或缓存整个事物并通过节点键查找,这可能是不切实际的,具体取决于树大小。在这里,让EF为您完成工作非常方便。

另一个常见的结构是类似于您的用户 /游戏方案的双向导航结构。在这里,修剪导航流向单个方向的情况通常并不不便。如果您忽略一个方向,可以说从游戏到团队,您仍然可以轻松查询所有团队是否对给定的游戏进行查询。因此:用户有游戏列表和团队列表。团队有游戏列表。游戏没有导航引用。为了让所有用户进行特定游戏,您可以写类似的内容:

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

其他提示

我找到了一个可行的解决方案(使用DTOS和AUTOMAPPER),该解决方案在下面复制,但我仍然希望答案列出 解决问题的方法 以示例,特别是这是一个理想的解决方案,或者我是否应该坚持使用导航属性,摆脱自动固定,以及序列化JSON的序列化,只是利用其他工作(属性等)...

因此,在我的视图模型中,我添加了几个课程:

public class GameDTO
{
    public int Id { get; set; }
    public int CreatorId { get; set; }

    public ICollection<UserTeamDTO> UserTeamsDTO { get; set; }
}

public class UserTeamDTO : UserTeam
{
    public UserProfile User { get; set; }
}

在我的控制器中,我使用自动应用程序将游戏 / UserTeam对象从存储库映射到我的DTO对象,然后将iList _gamesdto返回到视图。

var _games = _gameRepository.GetAllGames();

IList<GameDTO> _gamesDto = new List<GameDTO>();
IList<UserTeamDTO> _userteamsDto = new List<UserTeamDTO>();
GameDTO _gameDto = new GameDTO();
UserTeamDTO _userteamDto = new UserTeamDTO();
Mapper.CreateMap<Game, GameDTO>();
Mapper.CreateMap<UserTeam, UserTeamDTO>();

foreach (Game _game in _games)
{
    foreach (UserTeam _userteam in _game.UserTeams)
    {
        _userteamDto = Mapper.Map<UserTeamDTO>(_userteam);
        _userteamDto.User = _userRepository.GetUser(_userteam.UserId);
        _userteamsDto.Add(_userteamDto);
    }

    _gameDto = Mapper.Map<GameDTO>(_game);
    _gameDto.UserTeamsDTO = _userteamsDto;
    _gamesDto.Add(_gameDto);
}

我最近也遇到了类似的问题,这也影响了序列化的JSON对象。我决定从数据模型中删除循环引用。

我首先删除了创建循环引用的冗余导航属性。我确保我所产生的数据树是有道理的。这使我能够清楚哪些对象拥有哪些关系。

这也使EF无法自动推理我的关系。我必须使用Fluentapi指定一对多和多一的关系。我在这里找到了一个解决方案: https://stackoverflow.com/a/16719203/188785

希望这很有帮助。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top