У меня есть класс datamapper, который будет загружать любое свойство, которое не имеет прикрепленного к нему атрибута Lazy. У меня есть два объекта: государство и страна. У страны есть обратное отношение к государству, поскольку в нем содержится список всех государств этой страны, и государство имеет прямое отношение к стране, поскольку у нее есть страна собственности, которая охотно загружает страну, которая ему присваивается. Однако, если я попытаюсь извлечь один из этих объектов, скажем, что это состояние происходит:
Я не понимаю, как я могу избежать этого цикла. Поэтому в основном я ищу идеи. Я отправлю любой код, который кто-либо спросит, но этот процесс включает в себя множество строк кода, поэтому я не хотел наводнять вопрос кодом.
Спасибо заранее!
Edit:
Хорошо следуя совету Мэтта Хауэллса и более глубокому изучению шаблона datamapper, Мартин Фаулер действительно говорит о циклической ссылке на стр. 169 и 170. Его предложение состоит в том, чтобы использовать пустой объект и загрузить его в карту идентификации и вернуть его таким образом останавливая рекурсивную загрузку. Я прочитал этот параграф около 1000 раз, и я до сих пор не понимаю, как это останавливает загрузку, и за этим я теряюсь, когда и как я буду знать, когда загрузить этот пустой объект в мою личную карту. Прошу прощения за то, что я здесь плотный, но это, похоже, летит прямо над моей головой.
Еще раз спасибо.
Рассмотрите возможность загрузки объектов через репозиторий, который отслеживает, какие объекты были загружены.
Изменить: если вы делаете свой собственный ORM (и даже если это не так), я очень рекомендую книги Мартина Фаулера "Шаблоны архитектуры корпоративных приложений". Я смутно вспоминаю, как он говорил об этой ситуации цикла в книге, чтобы она могла помочь вам.
Изменить 2: На этапах 4 и 5 вашего цикла, если вы уже загрузили страну, нет необходимости загружать свои состояния, потому что они уже должны быть загружены. Это прерывает бесконечный цикл.
Дантаппер должен искать циклические ссылки. Это доморощенный datamapper?
Я просто хотел опубликовать решение, с которым я столкнулся, однако я считаю, что есть много способов скинуть этот кот.
Вот мой 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;
}
Вот оно, похоже, это делает. Все мои модульные тесты проходят. Спасибо за помощь всем. Надеюсь, это поможет кому-то позже. Еще раз, это, вероятно, было бы намного проще обернуть его в единицу рабочего шаблона, и в конечном итоге я могу это сделать, но на данный момент это выполняется.