Domanda

Sto cercando di capire il modo migliore per gestire il caricamento di oggetti con grafici diversi (entità correlate) a seconda del contesto in cui vengono utilizzati.

Ad esempio Ecco un esempio dei miei oggetti dominio:

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

Quello che sto cercando di capire è come caricare queste informazioni in modo diverso a seconda di come le sto usando.

Ad esempio, in prima pagina ho un elenco di tutti i puzzle. A questo punto non mi interessa davvero le soluzioni per il puzzle o i passaggi in quelle soluzioni (che possono diventare piuttosto pesanti). Tutto quello che voglio sono i puzzle. Vorrei caricarli dal mio controller in questo modo:

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

In seguito per la vista puzzle ora mi occupo solo delle soluzioni per l'utente corrente. Non voglio caricare l'intero grafico con tutte le soluzioni e tutti i passaggi.

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

All'interno del mio IPuzzleService, i miei metodi si presentano così:

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

Il caricamento lento non funziona davvero nel mondo reale, perché la mia sessione viene eliminata subito dopo ogni unità di lavoro. I miei controller non hanno alcun concetto di repository e quindi non gestiscono lo stato della sessione e non possono trattenerlo fino a quando la visualizzazione non viene renderizzata.

Sto cercando di capire quale sia lo schema giusto da usare qui. Ho diversi sovraccarichi sul mio servizio come GetPuzzleWithSolutionsAndVotes o più visualizzazione specifica come GetPuzzlesForDisplayView e GetPuzzlesForListView ?

Sto dando un senso? Sono lontano dalla base? Per favore aiutate.

È stato utile?

Soluzione

Ho avuto un caso simile in cui non potevo usare il caricamento lento.

Se hai solo bisogno di uno o due casi, allora la cosa più semplice come suggerisci, crea metodi GetPuzleWithXYZ () separati.

Puoi anche creare un piccolo oggetto query con un'interfaccia fluida.

Qualcosa come ...

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

quindi il metodo Get () del repository può creare un'istanza del generatore di espressioni e passarlo al chiamante

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

e le chiamate tipiche sembrano ...

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

ha bisogno di un po 'di lavoro, ma puoi vedere l'idea di base.

Altri suggerimenti

Non credo che il tuo servizio dovrebbe essere a conoscenza delle Viste. I tuoi requisiti potrebbero cambiare, quindi non legare i loro nomi per visualizzarli.

Quando chiami GetPuzzles () devi solo caricare il puzzle di root, e GetPuzzleById (int id) può caricare le associazioni.

Ad esempio nell'API criteri: .SetFetchMode (" Solutions " ;, NHibernate.FetchMode.Join)

Non capisco perché non riesci a caricare lentamente. Se si utilizza nHibernate, il proxy tornerà al database automaticamente quando si accede alla proprietà. Il controller dovrebbe ottenere tutti i dati necessari. Non è necessario passare un proxy non caricato alla vista, quindi la vista deve gestire il caso in cui non è possibile caricare i dati.

Quindi dovresti fare in modo che il controller carichi i dati specifici di cui hai bisogno, per caricare solo per un utente, cambierei l'interfaccia in modo che: GetPuzzle(puzzleId,user)

In questo metodo puoi semplicemente caricare i dati per un solo utente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top