Question

J'ai une classe datamapper qui chargera avec impatience toute propriété qui ne possède pas d'attribut Lazy. J'ai deux entités, Etat et Pays, le pays a une relation inverse à déclarer en ce sens qu'il contient une liste de tous les états de ce pays et que l'Etat a une relation en aval avec le pays en ce sens qu'il a un pays de propriété qui charge avec impatience le pays qui il est assigné à. Cependant, si j'essaie de récupérer l'un de ces objets, disons un état, voici ce qui se produit:

  1. l'état est chargé par le mappeur
  2. Le mappeur atteint une propriété très désirée
  3. Le mappeur récupère le pays pour cet état
  4. Mapper charge le pays
  5. Mapper atteint une propriété de collection des États
  6. Le mappeur charge une liste d'états et commence à mapper chaque individu à l'aide du cache, dans la mesure du possible.
  7. GOTO 1 pour chaque état chargé dans le pays

Je ne sais pas comment éviter cette boucle. Je cherche donc principalement des idées. Je publierai tout code demandé par n'importe qui, mais ce processus englobe BEAUCOUP de lignes de code et je ne voulais donc pas submerger la question de code.

Merci d'avance!

Modifier:

Très bien, après avoir suivi les conseils de Matt Howells et approfondi ses recherches sur le modèle de datamapper, Martin Fowler parle bien d’une référence cyclique aux pages 169 et 170. Il suggère d’utiliser un objet vide et de le charger dans une carte d’identité et de le renvoyer ainsi. arrêter le chargement récursif. J'ai lu ce paragraphe environ 1000 fois maintenant et je ne comprends toujours pas comment cela arrête la charge et au-delà, je ne sais plus quand ni comment je saurais quand charger cet objet vide dans ma carte d'identité. Je m'excuse d'être dense ici, mais cela semble juste voler au-dessus de ma tête.

Merci encore.

Était-ce utile?

La solution

Envisagez de charger des objets via un référentiel qui garde la trace des objets chargés.

Éditer: Si vous faites votre propre ORM (et même si vous ne l’êtes pas), je recommande vivement le livre de Martin Fowler, Patterns of Enterprise Application Architecture. Je me souviens vaguement de lui avoir parlé de cette situation de boucle dans le livre afin que cela puisse vous aider.

Modifier 2: Aux étapes 4 et 5 de votre boucle, si vous avez déjà chargé le pays, vous n'avez pas besoin de charger ses états avec empressement, car ils doivent déjà être chargés. Cela rompt la boucle infinie.

Autres conseils

Le datamapper doit capturer des références circulaires. Est-ce un datamapper local?

Je voulais simplement publier la solution que j'ai proposée, mais je pense qu'il existe de nombreuses façons de peauner ce chat.

Voici mon FetchDepthCounterClass que j'ai créé:

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 renvoie une valeur booléenne indiquant si la profondeur d'extraction maximale a été atteinte ou non. J'appelle le compteur d'incrément dans le cadre de mon processus de mappage juste avant de définir la valeur de la propriété. Tout d'abord, je détermine que je dois charger un autre objet DTO ou une collection de DTO, puis je passe le type parent et l'incrémente sur ce type. Voici donc le petit bout de code dans ma méthode SetValue dans mon datamapper:

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

C'est ça, ça semble le faire. Tous mes tests unitaires sont réussis. Merci pour l'aide de tous. J'espère que cela aidera quelqu'un plus tard. Encore une fois, cela aurait probablement été beaucoup plus facile de l'intégrer dans une unité de régime de travail, et je pourrais éventuellement le faire, mais cela accomplit le travail pour l'instant.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top