¿Cómo controlo la profundidad de alcance de un intercambiador de datos de carga impaciente?

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

Pregunta

Tengo una clase de intercambio de datos que cargará cualquier propiedad que no tenga un atributo perezoso adjunto. Tengo dos entidades, State y Country, Country tiene una relación inversa con state en que contiene una lista de todos los estados de ese país y State tiene una relación directa con Country en que tiene una propiedad Country que ansiosamente carga el país que se asigna a Sin embargo, si intento recuperar uno de estos objetos, digamos un estado: esto es lo que sucede:

  1. El estado lo carga el asignador
  2. El asignador llega a una propiedad ansiosa País
  3. Mapper recupera el país para ese estado
  4. El asignador carga el país
  5. El asignador llega a una propiedad de recopilación impaciente de los estados
  6. El asignador carga una lista de estados y comienza a mapear cada uno de ellos usando el caché donde puede.
  7. GOTO 1 para cada estado cargado en el país

No sé cómo puedo evitar este bucle. Así que principalmente estoy buscando ideas. Publicaré cualquier código que me pidan, pero este proceso abarca MUCHAS líneas de código, por lo que no quería inundar la pregunta con código.

Gracias de antemano!

Editar:

Muy bien, después de seguir los consejos de Matt Howell e investigar más a fondo el patrón del mapeador de datos, Martin Fowler sí habla de una referencia cíclica en las páginas 169 y 170. Su sugerencia es usar un objeto vacío y cargarlo en un mapa de identidad y devolverlo así Deteniendo la carga recursiva. He leído este párrafo unas 1000 veces y todavía no entiendo cómo esto detiene la carga y más allá de eso, me pierdo cuándo o cómo sabría cuándo cargar este objeto vacío en mi mapa de identidad. Pido disculpas por ser denso aquí, pero esto parece estar volando sobre mi cabeza.

Gracias de nuevo.

¿Fue útil?

Solución

Considere cargar objetos a través de un repositorio que realiza un seguimiento de los objetos que se han cargado.

Editar: si está haciendo su propio ORM (e incluso si no lo está), le recomiendo el libro Patrones de arquitectura de aplicaciones empresariales de Martin Fowler. Recuerdo vagamente que él habló sobre esta situación de bucle en el libro, por lo que podría ayudarte.

Edición 2: En los pasos 4 y 5 de su ciclo, si ya ha cargado el país, entonces no hay necesidad de cargar con entusiasmo sus estados porque ya deberían estar cargados. Esto rompe el ciclo infinito.

Otros consejos

El intercambiador de datos debe capturar referencias circulares. ¿Es un intercambio de datos de cosecha propia?

Solo quería publicar la solución que se me ocurrió, sin embargo, creo que hay muchas maneras de despellejar a este gato.

Aquí está mi FetchDepthCounterClass que creé:

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 devuelve un valor bool que indica si se ha alcanzado o no la profundidad máxima de extracción. Llamo al contador de incrementos como parte de mi proceso de mapeo justo antes de establecer el valor de la propiedad. Primero, determino que lo que tengo que cargar es otro objeto DTO o una colección de DTO y paso el tipo parent y el incremento en ese tipo. Entonces este es el pequeño fragmento de código dentro de mi método SetValue en mi datamapper:

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

Eso es, eso parece hacerlo. Todas mis pruebas de unidad están pasando. Gracias por la ayuda de todos. Espero que esto ayude a alguien más adelante. Una vez más, esto probablemente hubiera sido mucho más fácil envolviéndolo en una unidad de patrón de trabajo, y eventualmente podría hacerlo, pero esto hace el trabajo por ahora.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top