Как я могу контролировать глубину выборки загружаемой datamapper?

2

У меня есть класс datamapper, который будет загружать любое свойство, которое не имеет прикрепленного к нему атрибута Lazy. У меня есть два объекта: государство и страна. У страны есть обратное отношение к государству, поскольку в нем содержится список всех государств этой страны, и государство имеет прямое отношение к стране, поскольку у нее есть страна собственности, которая охотно загружает страну, которая ему присваивается. Однако, если я попытаюсь извлечь один из этих объектов, скажем, что это состояние происходит:

  • Состояние загружается mapper
  • Mapper достигает желаемого свойства Страна
  • Mapper возвращает страну для этого состояния.
  • Mapper загружает страну
  • Mapper достигает целевого свойства коллекции состояний
  • Mapper загружает список состояний и начинает отображать каждый отдельный, используя кеш, где он может.
  • GOTO 1 для каждого состояния, загруженного в страну.

Я не понимаю, как я могу избежать этого цикла. Поэтому в основном я ищу идеи. Я отправлю любой код, который кто-либо спросит, но этот процесс включает в себя множество строк кода, поэтому я не хотел наводнять вопрос кодом.

Спасибо заранее!

Edit:

Хорошо следуя совету Мэтта Хауэллса и более глубокому изучению шаблона datamapper, Мартин Фаулер действительно говорит о циклической ссылке на стр. 169 и 170. Его предложение состоит в том, чтобы использовать пустой объект и загрузить его в карту идентификации и вернуть его таким образом останавливая рекурсивную загрузку. Я прочитал этот параграф около 1000 раз, и я до сих пор не понимаю, как это останавливает загрузку, и за этим я теряюсь, когда и как я буду знать, когда загрузить этот пустой объект в мою личную карту. Прошу прощения за то, что я здесь плотный, но это, похоже, летит прямо над моей головой.

Еще раз спасибо.

Теги:
database
design-patterns
c#-2.0

3 ответа

2
Лучший ответ

Рассмотрите возможность загрузки объектов через репозиторий, который отслеживает, какие объекты были загружены.

Изменить: если вы делаете свой собственный ORM (и даже если это не так), я очень рекомендую книги Мартина Фаулера "Шаблоны архитектуры корпоративных приложений". Я смутно вспоминаю, как он говорил об этой ситуации цикла в книге, чтобы она могла помочь вам.

Изменить 2: На этапах 4 и 5 вашего цикла, если вы уже загрузили страну, нет необходимости загружать свои состояния, потому что они уже должны быть загружены. Это прерывает бесконечный цикл.

  • 0
    Я действительно отслеживаю все объекты, которые были загружены. Тем не менее, и я думаю, что я просто плотный, я не могу понять, каким образом я могу использовать это. Я пытаюсь контролировать глубину извлечения, но она должна контролироваться специально для автора. То, чего я пытаюсь достичь, это, по сути, следующее: Штат (Отправитель) -> Страна -> Штаты -> [СТОП], но когда я сопоставляю каждое отдельное государство, находящееся в Штатах, субъекты не имеют понятия о существовании отправителя запроса. , Таким образом, кажется, что применение счетчика, относящегося к составителю, не может быть и речи. Да?
  • 0
    У меня это на рабочем столе, посмотрим, смогу ли я найти что-нибудь завтра. Спасибо.
Показать ещё 1 комментарий
1

Дантаппер должен искать циклические ссылки. Это доморощенный datamapper?

  • 0
    Это доморощенный ..... как бы я реализовать какую-то форму улова для этого? Вот где я затрудняюсь откорректировать свой код datamapper, чтобы включить часы для этого.
  • 0
    Запишите свойства, которые вы уже посетили, и сравните текущее свойство с этим списком.
Показать ещё 1 комментарий
0

Я просто хотел опубликовать решение, с которым я столкнулся, однако я считаю, что есть много способов скинуть этот кот.

Вот мой FetchDepthCounterClass, который я создал:

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 возвращает bool, указав, достигнута ли максимальная глубина выборки или нет. Я вызываю счетчик инкремента как часть процесса сопоставления непосредственно перед установкой значения свойства. Сначала я определяю, что мне нужно загрузить другой объект DTO или коллекцию DTO, и я передаю родительский тип и приращение этого типа. Итак, это маленький маленький код внутри моего метода SetValue в моем datamapper:

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

Вот оно, похоже, это делает. Все мои модульные тесты проходят. Спасибо за помощь всем. Надеюсь, это поможет кому-то позже. Еще раз, это, вероятно, было бы намного проще обернуть его в единицу рабочего шаблона, и в конечном итоге я могу это сделать, но на данный момент это выполняется.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню