Come posso controllare la profondità di recupero di un datamapper di caricamento desideroso?

StackOverflow https://stackoverflow.com/questions/1201924

Domanda

Ho una classe datamapper che desidererà caricare qualsiasi proprietà a cui non sia associato un attributo Lazy. Ho due entità, Stato e Paese, Paese ha una relazione inversa da dichiarare in quanto contiene un elenco di tutti gli stati di quel Paese e Stato ha una relazione diretta con Paese in quanto ha un Paese di proprietà che desidera caricare il Paese che è assegnato a. Tuttavia, se provo a recuperare uno di questi oggetti, diciamo uno stato, ecco cosa succede:

  1. Lo stato viene caricato dal mapper
  2. Mapper raggiunge un Paese di proprietà desideroso
  3. Mapper recupera il Paese per quello stato
  4. Mapper carica il paese
  5. Mapper raggiunge una proprietà raccolta desiderosa degli Stati
  6. Mapper carica un elenco di stati e inizia a mappare ciascuno di essi utilizzando la cache dove possibile.
  7. GOTO 1 per ogni stato caricato nel paese

Sono in perdita su come posso evitare questo ciclo. Quindi principalmente cerco idee. Pubblicherò qualsiasi codice che qualcuno chieda, ma questo processo comprende MOLTE righe di codice, quindi non volevo inondare la domanda con il codice.

Grazie in anticipo!

Modifica:

Va ??bene dopo aver seguito i consigli di Matt Howells e aver studiato a fondo il modello di datamapper Martin Fowler parla in effetti di un riferimento ciclico a pagina 169 e 170. Il suo suggerimento è di usare un oggetto vuoto e caricarlo in una mappa di identità e restituirlo così interruzione del caricamento ricorsivo. Ho letto questo paragrafo circa 1000 volte e non riesco ancora a capire come questo interrompe il carico e oltre a ciò mi sono perso su quando o come avrei saputo quando caricare questo oggetto vuoto nella mia mappa di identità. Mi scuso per essere denso qui, ma questo sembra volare proprio sopra la mia testa.

Grazie ancora.

È stato utile?

Soluzione

Considera di caricare oggetti attraverso un repository che tiene traccia di quali oggetti sono stati caricati.

Modifica: se stai realizzando il tuo ORM (e anche se non lo sei), consiglio vivamente il libro Patterns of Enterprise Application Architecture di Martin Fowler. Ricordo vagamente che parlava di questa situazione del ciclo nel libro, quindi potrebbe aiutarti.

Modifica 2: Ai passaggi 4 e 5 del tuo ciclo se hai già caricato il paese, non è necessario caricare con entusiasmo i suoi stati perché dovrebbero già essere caricati. Questo interrompe il ciclo infinito.

Altri suggerimenti

Il datamapper dovrebbe acquisire riferimenti circolari. È un datamapper nostrano?

Volevo solo pubblicare la soluzione che mi è venuta in mente, tuttavia credo che ci siano molti modi per scuoiare questo gatto.

Ecco la mia FetchDepthCounterClass che ho creato:

public static class FetchDepthCounter
{
    private static Dictionary<Type, int> _DepthCounter;
    private static int _MaxDepth = 3;

    static FetchDepthCounter()
    {   
        _DepthCounter = new Dictionary<Type, int>();
    }

    public static void SetDepth(int depth)
    {
        _MaxDepth = depth;
    }

    public static void ResetCounter()
    {
        _DepthCounter.Clear();
    }

    public static bool IncrementCounter(Type entityType)
    {
        if(!_DepthCounter.ContainsKey(entityType))
        {
            _DepthCounter.Add(entityType, 0);
            return true;
        }

        if(_DepthCounter[entityType] < _MaxDepth)
        {
            ++_DepthCounter[entityType];
            return true;
        }

        return false;
    }

}

IncrementCounter restituisce un valore booleano che indica se la profondità di recupero massima è stata raggiunta o meno. Chiamo contatore di incrementi come parte del mio processo di mappatura subito prima di impostare il valore della proprietà. Per prima cosa determino che ciò che devo caricare è un altro oggetto DTO o una raccolta di DTO e passo il tipo parent e incremento su quel tipo. Quindi questo è un po 'di codice all'interno del mio metodo SetValue nel mio datamapper:

if(isDto)
{
    if (!FetchDepthCounter.IncrementCounter(property.ComponentType))
        return;
}

Ecco fatto, sembra farlo. Tutti i miei test unitari stanno superando. Grazie per l'aiuto di tutti. Spero che questo aiuti qualcuno in seguito. Ancora una volta, questo probabilmente sarebbe stato molto più semplice racchiuderlo in un'unità di modello di lavoro, e alla fine potrei farlo, ma per ora il lavoro è svolto.

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