Frage

Ich habe eine Lösung gefunden, die funktioniert (unter Verwendung von DTOs und Automapper), die unten reproduziert wird, aber ich würde eine Antwort bevorzugen, die die auflistet Unterschiedliche Ansätze für das Problem Mit Beispielen und dies wird als Antwort markiert, wenn sie empfangen werden.

In meinem Entitätsmodell habe ich eine Navigationseigenschaft, die von einer Kindergesellschaft zum übergeordneten Unternehmen übernimmt. Mein Projekt funktionierte schwimmend. Dann begann ich, eine Autofixur für Unit -Tests zu verwenden, und das Testen fehlgeschlagen, Autofixure besagte, dass ich eine kreisförmige Referenz hatte.

Jetzt ist mir klar, dass wie dieser kreisförmige Referenznavigationseigenschaften im Entitätsgerüst in Ordnung sind, aber ich habe diesen Beitrag gefunden ((Verwenden Sie den Wert einer übergeordneten Eigenschaft bei der Erstellung eines komplexen Kindes in der Autofixure), wo Mark Seemann, der Schöpfer der Autofixure, erklärt:

"Für die Aufzeichnung habe ich jahrelang keine API mit einer kreisförmigen Referenz nicht mehr geschrieben, daher ist es durchaus möglich, diese Eltern/Kinderbeziehungen zu vermeiden."

Ich möchte also verstehen, wie ein Domänenmodell neu gestaltet werden kann, um Kinder-/Elternbeziehungen zu vermeiden.

Im Folgenden finden Sie die fraglichen Entitätsklassen, die Repository -Methode und wie ich die Eigenschaft verwende, die meiner Ansicht nach die kreisförmige Referenz verursacht. Die perfekte Antwort würde die verschiedenen Optionen erläutern, aus denen ich mit Beispielen auswählen kann, und die grundlegenden Voraussetzungen jedes Ansatzes.

HINWEIS: Die Eigenschaft, die die kreisförmige Referenz verursacht, ist Benutzer im UserTeam -Modell.

Modelle:

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; }
}

Repository -Methode

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;
        }
    }

Aussicht

@model IEnumerable<Game>
@foreach (var item in Model){
    foreach (var userteam in item.UserTeams){
        <p>@userteam.User.UserName</p>
    }
}

Wenn ich nun die Navigationseigenschaft von 'Benutzer' entferne, könnte ich nicht in der Lage sein, '@Userteam.user.username' zu machen

Wie kann ich das Domänenmodell umgestalten, um die kreisförmige Referenz zu entfernen, während ich in der Lage bin, leicht durch Spiele zu gehen und so etwas wie UserTeam.User.username zu machen?

War es hilfreich?

Lösung

Ich hatte ein Ähnliches Problem mit Autofixure und EntityFramework vor einiger Zeit. Meine Lösung bestand darin, die Autofixure eine Erweiterung hinzuzufügen, mit der Sie eine SUT mit ein paar Rekursionen erstellen können. Diese Erweiterung wurde kürzlich in Autofixure übernommen.

Ich verstehe jedoch, dass es in Ihrer Frage nicht darum ging, wie man Autofixure -Konstrukt rekursive Datenstrukturen durchführt, was in der Tat möglich ist, sondern wie man Domänenmodelle ohne Rekursion erstellt.

Zunächst haben Sie Baum- oder Graphenstrukturen. Hier würde alles andere als Rekursion durch lose gekoppelte Knoten -IDs eine Indirektion bedeuten. Anstatt eine Assoziation zu definieren, müssten Sie die Baumfrage für den Abfragen durchquer durchqueren oder das Ganze zwischenstrahlen und durch die Knotenschluchung durchqueren, was je nach Baumgröße unpraktisch sein kann. Hier ist es sehr praktisch, dass EF die Arbeit für Sie erledigt.

Die andere gemeinsame Struktur ist eine wechselseitige Navigationsstruktur, die Ihrem Benutzer- / Spielszenario ähnelt. Hier ist es oft nicht so unpraktisch, den Navigationsfluss in eine einzelne Richtung zu beschneiden. Wenn Sie eine Richtung weglassen, sagen Sie von Spiel zu Team, können Sie immer noch alle Teams für ein bestimmtes Spiel problemlos abfragen. Also: Der Benutzer hat eine Liste von Spielen und eine Liste von Teams. Das Team hat eine Liste von Spielen. Spiele haben keinen Navigationsverweis auf auch. Um alle Benutzer für ein bestimmtes Spiel zu erhalten, können Sie so etwas schreiben wie:

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

Andere Tipps

Ich habe eine Lösung gefunden, die funktioniert (unter Verwendung von DTOs und Automapper), die unten reproduziert wird, aber ich würde immer noch eine Antwort bevorzugen, die die auflistet Unterschiedliche Ansätze für das Problem Insbesondere bei Beispielen, insbesondere, ob dies eine wünschenswerte Lösung ist oder ob ich mich so an die Navigationseigenschaften halten sollte, beseitigen Sie die Autofixe, und wenn es um die Serialisierung für JSON geht, verwenden Sie nur andere Arbeiten (Attribute usw.) ...

Meiner Ansichtsmodell habe ich also ein paar Klassen hinzugefügt:

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; }
}

Und in meinem Controller verwende ich Automapper, um die Spiele / Userteam -Objekte aus dem Repository an meine DTO -Objekte zuzuordnen und den ilist _gamesdto an die Ansicht zurückzugeben.

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);
}

Ich hatte kürzlich ein ähnliches Problem, das sich auch auf die Serialisierung von JSON -Objekten auswirkte. Ich beschloss, die kreisförmigen Referenzen aus meinem Datenmodell zu entfernen.

Ich habe zuerst die redundanten Navigationseigenschaften entfernt, die die kreisförmigen Referenzen erstellten. Ich habe dafür gesorgt, dass mein resultierender Datenbaum sinnvoll war. Dies ermöglichte mir klar, welche Objekte welche Beziehungen besitzen.

Dies machte EF auch nicht in der Lage, automatisch über meine Beziehungen zu sprechen. Ich musste die Eins-zu-Viele- und viele zu viele Beziehungen mit den fließenden Beziehungen angeben. Ich habe hier eine Lösung gefunden: https://stackoverflow.com/a/16719203/1887885

Hoffe das ist hilfreich.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top