Pergunta

Eu tenho uma classe DataMapper que irá carregar ansioso qualquer propriedade que não tem um atributo preguiçoso ligado a ele. Eu tenho duas entidades, estado e país, País tem uma relação inversa ao estado em que ele contém uma lista de todos os estados do país e Estado tem um relacionamento para a frente para País na medida em que tem uma propriedade rural que carrega ansiosos o país que ele é atribuído a. No entanto, se eu tentar e recuperar um desses objetos, digamos que um Estado é isso que acontece:

  1. Estado é carregado pelo mapeador
  2. Mapper atinge uma propriedade ansiosos País
  3. Mapper recupera o país para esse estado
  4. Mapper carrega o país
  5. Mapper atinge uma propriedade coleção ansiosos dos Estados
  6. mapeador carrega uma lista de estados e começa mapeando cada um indivíduo usando o cache onde ele pode.
  7. GOTO 1 para cada estado carregado no país

Eu estou em uma perda a respeito de como eu posso evitar este loop. Então principalmente Estou à procura de ideias. Vou postar qualquer código alguém perguntar, mas este processo abrange um monte de linhas de código para que eu não queria inundar a questão com o código.

Agradecemos antecipadamente!

Editar:

Tudo bem, depois de seguir o conselho Matt Howells e investigar mais profundamente o padrão DataMapper Martin Fowler não realmente falar sobre uma referência cíclica na página 169 e 170. Sua sugestão é usar um objeto vazio e carregá-lo em um mapa de identidade e devolvê-lo assim, parar o carregamento recursivo. Eu li este parágrafo cerca de 1000 vezes e agora eu ainda não entendo como isso interrompe a carga e além disso estou perdido a respeito de quando ou como eu iria saber quando carregar este objeto vazio em meu mapa de identidade. Peço desculpas por ser densa aqui, mas isso só parece estar voando para a direita sobre a minha cabeça.

Obrigado novamente.

Foi útil?

Solução

Considere carregar objetos através de um repositório que mantém o controle de quais objetos foram carregados.

Edit: Se você estiver fazendo seu próprio ORM (e mesmo se você não é) eu recomendo Patterns livro de Martin Fowler do Enterprise Application Architecture. Lembro-me vagamente dele falando sobre esta situação de loop no livro para que ele possa ajudá-lo.

Edit 2: No passos 4 e 5 do seu loop se você já tiver carregado o país, então não há necessidade de carregar ansiosamente seus estados, porque eles já deve estar carregado. Isso quebra o loop infinito.

Outras dicas

O DataMapper deve pegar referências circulares. É um homegrown DataMapper?

Eu só queria postar a solução que eu vim com, porém eu acredito que há muitas maneiras de esfolar este gato.

Aqui está o meu FetchDepthCounterClass eu criei:

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 retorna um bool indicando se o máximo buscar profundidade foi atingido ou não. Eu chamo contador de incremento como parte do meu processo de mapeamento bem antes de eu definir o valor da propriedade. Primeiro eu determinar que o que eu estou tendo que carga é outro objeto DTO ou uma coleção de DTOs e eu passar o pai tipo e incremento nesse tipo. Portanto, esta é a pequena pouco de código dentro do meu método SetValue na minha DataMapper:

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

Isso é que é, que parece fazê-lo. Todos os meus testes de unidade estão passando. Obrigado pela ajuda de todos. Espero que isso ajude alguém mais tarde. Mais uma vez, isso provavelmente teria sido muito mais fácil de embrulho-lo em uma unidade de padrão de trabalho e, finalmente, eu posso fazer isso, mas isso começa o trabalho feito por agora.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top