1

Ich versuche herauszufinden, wie man Objekte mit verschiedenen Graphen (verwandte Entitäten) laden kann, je nachdem in welchem ​​Kontext sie verwendet werden.Das richtige Muster zum Laden von Objekten mit verschiedenen Diagrammen finden

Zum Beispiel ist hier eine Probe meiner Domain-Objekte:

public class Puzzle 
{ 
    public Id{ get; private set; } 
    public string TopicUrl { get; set; } 
    public string EndTopic { get; set; } 
    public IEnumerable<Solution> Solutions { get; set; } 
    public IEnumerable<Vote> Votes { get; set; } 
    public int SolutionCount { get; set; } 
    public User User { get; set; } 
} 
public class Solution 
{ 
    public int Id { get; private set; } 
    public IEnumerable<Step> Steps { get; set; } 
    public int UserId { get; set; } 
} 
public class Step 
{ 
    public Id { get; set; } 
    public string Url { get; set; } 
} 
public class Vote 
{ 
    public id Id { get; set; } 
    public int UserId { get; set; } 
    public int VoteType { get; set; } 
} 

Was ich versuche zu verstehen, wie diese Informationen anders zu laden, je nachdem, wie ich es bin mit.

Zum Beispiel habe ich auf der Titelseite eine Liste aller Rätsel. An dieser Stelle interessiert mich nicht wirklich die Lösungen für das Puzzle oder für die Schritte in diesen Lösungen (die ziemlich stark werden können). Alles was ich will sind die Rätsel. Ich würde sie von meinem Controller wie folgt laden:

public ActionResult Index(/* parameters */) 
{ 
    ... 
    var puzzles = _puzzleService.GetPuzzles(); 
    return View(puzzles); 
} 

Später für das Puzzle Ansicht mich interessiert jetzt nur die Lösungen für den aktuellen Benutzer. Ich möchte nicht den gesamten Graphen mit allen Lösungen und allen Schritten laden.

public ActionResult Display(int puzzleId) 
{ 
    var puzzle = _accountService.GetPuzzleById(puzzleId); 
    //I want to be able to access my solutions, steps, and votes. just for the current user. 
} 

Inside my IPuzzleService, schauen meine Methoden wie folgt aus:

public IEnumerable<Puzzle> GetPuzzles() 
{ 
    using(_repository.OpenSession()) 
    { 
     _repository.All<Puzzle>().ToList(); 
    } 
} 
public Puzzle GetPuzzleById(int puzzleId) 
{ 
    using(_repository.OpenSession()) 
    { 
     _repository.All<Puzzle>().Where(x => x.Id == puzzleId).SingleOrDefault(); 
    } 
} 

Lazy Loading in der realen Welt nicht wirklich funktionieren, weil meine Sitzung direkt nach jeder Arbeitseinheit angeordnet wird. Meine Controller haben kein Konzept für das Repository und verwalten daher den Sitzungsstatus nicht und können ihn nicht behalten, bis die Ansicht gerendert wird.

Ich versuche herauszufinden, was das richtige Muster hier zu verwenden ist. Habe ich verschiedene Überladungen an meinem Service wie GetPuzzleWithSolutionsAndVotes oder mehr spezifische wie GetPuzzlesForDisplayView und GetPuzzlesForListView?

Mache ich Sinn? Bin ich weit weg von der Basis? Bitte helfen Sie.

Antwort

2

Ich hatte einen ähnlichen Fall, in dem ich nicht Lazy laden konnte.

Wenn Sie nur ein oder zwei Fälle benötigen, dann erstellen Sie am einfachsten separate Methoden GetPuzleWithXYZ().

Sie könnten auch ein kleines Abfrageobjekt mit einer fließenden Oberfläche erstellen. wie

Etwas ...

public interface IPuzzleQuery 
{ 
    IPuzzleLoadWith IdEquals(int id); 
} 

public interface IPuzzleLoadWith 
{ 
    ISolutionLoadWith WithSolutions(); 

    IPuzzleLoadWith WithVotes(); 
} 

public interface ISolutionLoadWith 
{ 
    IPuzzleLoadWith AndSteps(); 
} 

public class PuzzleQueryExpressionBuilder : IPuzzleQuery, IPuzzleLoadWith, ISolutionLoadWith 
{ 
    public int Id { get; private set; } 
    public bool LoadSolutions { get; private set; } 
    public bool LoadVotes { get; private set; } 
    public bool LoadSteps { get; private set; } 

    public IPuzzleLoadWith IdEquals(int id) 
    { 
     Id = id; 
     return this;  
    } 

    public ISolutionLoadWith WithSolutions() 
    { 
     LoadSolutions = true; 
     return this; 
    } 

    public IPuzzleLoadWith WithVotes() 
    { 
     LoadVotes = true; 
     return this; 
    } 

    public IPuzzleLoadWith AndSteps() 
    { 
     LoadSteps = true; 
     return this; 
    } 
} 

dann Repository Get() -Methode, die Expression Builder instanziieren und es an den Aufrufer übergeben

public Puzzle Get(Action<IPuzzleQuery> expression) 
{ 
    var criteria = new PuzzleQueryExpressionBuilder(); 

    expression(criteria); 

    var query = _repository.All<Puzzle>().Where(x => x.Id == criteria.Id) 

    if(criteria.LoadSolutions) .... 

    if(criteria.LoadSteps) .... 

    if(criteria.LoadVotes) .... 

    ... 
    ... 

    return query.FirstOrDefault(); 
} 

und typische Anrufe aussehen würde ...

Puzzle myPuzzle = Repository.Get(where => where.IdEquals(101).WithSolutions()); 

Puzzle myPuzzle = Repository.Get(where => where.IdEquals(101).WithSolutions().AndSteps()); 

Puzzle myPuzzle = Repository.Get(where => where.IdEquals(101).WithVotes().WithSolutions()); 

es braucht ein wenig Arbeit, aber Sie können die Grundidee sehen.

0

Ich glaube nicht, dass Ihr Dienst die Ansichten kennen sollte. Ihre Anforderungen können sich ändern, also binden Sie ihre Namen nicht an Namen.

Wenn Sie GetPuzzles() aufrufen, sollten Sie nur root puzzle laden, und GetPuzzleById (int id) kann die Verknüpfungen geladen werden.

Zum Beispiel in Kriterien API: .SetFetchMode("Solutions", NHibernate.FetchMode.Join)

Ich verstehe nicht, warum du faul Last kann nicht. Wenn Sie nHibernate verwenden, wird der Proxy beim Zugriff auf die Eigenschaft wieder in die Datenbank zurückversetzt. Ihr Controller sollte alle Daten erhalten, die Sie benötigen. Sie sollten keinen nicht geladenen Proxy an Ihre Ansicht übergeben, da Ihre Ansicht den Fall behandeln muss, in dem die Daten nicht geladen werden können.

So sollten Sie Controller die spezifischen Teile der Daten laden Sie benötigen, für einen Benutzer nur zu laden, würde ich die Schnittstelle ändern, so dass: GetPuzzle(puzzleId,user)

Bei dieser Methode können Sie nur eifrig Last die Daten für die ein Benutzer.

+0

Mein Verstand ist ein wenig verschwommen im Moment hoffe ich, dass dies für Sie sinnvoll ist und bietet einen gewissen Wert – JoshBerke

+0

Ich kann nicht faul laden, weil wenn Sitzung am Ende der GetPuzzle ... X() -Methoden außerhalb des Geltungsbereichs geht es ist entsorgt. Wenn der Proxy versucht, die Elemente später abzurufen, erhalte ich den Fehler "Sitzung ist bereits erledigt". – Micah

Verwandte Themen