Как я могу кодировать рекурсивный поиск связанных объектов базы данных? - PullRequest
0 голосов
/ 27 марта 2019

Я создаю динамический CDN для внутреннего использования на работе.У нас есть огромное количество веб-приложений, которые мы использовали в бизнесе и настраиваем CDN, чтобы все библиотеки JS (Bootstrap, Jquery и т. Д.) Работали.Чтобы помочь в создании проекта, мы создали базу данных, в которой у нас есть таблица для библиотек, а также таблица для требований библиотеки (т. Е. Bootstrap требует Jquery).Используя данные в базе данных о требованиях, webAPI вернет список, содержащий теги сценария и теги css link для использования на страницах _Layout.cshtml.

Обсуждаемые таблицы базы данных: tblLibrary & tblLibraryRequirements

Таблица tblLibraryRequirements состоит из следующих столбцов: - ID - [ID библиотеки] - [Требуется ID]

У меня есть рабочиймодель, которая углубляется на 3 уровня, путем вложения циклов foreach для добавления объекта требования tblLibrary в основной список всех соответствующих библиотек.Дубликаты удаляются с помощью .Distinct ()

        public ActionResult<List<string>> GetSciptTags_config(int ConfigID)
        {
            List<TblLibrary> LibraryRecsToScript = new List<TblLibrary>();

            // Get a list of libraries in the project config
            List<TblProjectConfigLibraries> configLibraries = db.TblProjectConfigLibraries.Where(s => s.ConfigurationId == ConfigID).ToList();

            foreach (TblProjectConfigLibraries configLibRec in configLibraries)
            {
                // get the tblLibrary record for the supplied ID
                TblLibrary libRec = db.TblLibrary.FirstOrDefault(s => s.Id == configLibRec.LibraryId);

                // find any requirement libraries
                List<TblLibraryRequirements> requirementRecs = db.TblLibraryRequirements.Where(s => s.LibraryId == configLibRec.LibraryId).ToList();

                foreach (TblLibraryRequirements item in requirementRecs)
                {
                    TblLibrary reqLibRec = db.TblLibrary.FirstOrDefault(s => s.Id == item.RequiresId);
                    // check that the requirement doesnt have requirements
                    List<TblLibraryRequirements> reqs = db.TblLibraryRequirements.Where(s => s.LibraryId == reqLibRec.Id).ToList();
                    foreach (TblLibraryRequirements req in reqs)
                    {
                        TblLibrary reqLibRec2 = db.TblLibrary.FirstOrDefault(s => s.Id == req.RequiresId);
                        LibraryRecsToScript.Add(reqLibRec2);
                    }
                    LibraryRecsToScript.Add(reqLibRec);
                }
                LibraryRecsToScript.Add(libRec);

            }

            // Remove Duplicates
            LibraryRecsToScript = LibraryRecsToScript.Distinct().ToList();
            // Get Scripts
            List<string> scripts = getScriptTags(LibraryRecsToScript);
            return scripts;
        }

Вышеприведенное работает для первых 3 уровней, но возьмите имеющуюся у нас библиотеку css, для которой требуется Bootstrap-DatePicker, тогда я бы хотел, чтобы это пошло еще доJQuery.

-ie library1 зависит от libraray2, который зависит от library3, который зависит от library4 и т. Д.

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

Любая помощь очень ценится.Извиняюсь за орфографию, грамматику и проблемы с форматированием.

1 Ответ

0 голосов
/ 28 марта 2019

Я нашел решение. Это может быть не так элегантно, как могло бы быть, но, похоже, это работает в моих тестах.

Я обновил действие контроллера, чтобы теперь вызывать функцию, передающую начальный идентификатор

 public ActionResult<List<string>> GetSciptTags_config(int ConfigID)
        {
            List<TblLibrary> LibraryRecsToScript = new List<TblLibrary>();

            // Get a list of libraries in the project config
            List<TblProjectConfigLibraries> configLibraries = db.TblProjectConfigLibraries.Where(s => s.ConfigurationId == ConfigID).ToList();

            foreach (TblProjectConfigLibraries configLibRec in configLibraries)
            {
                LibraryRecsToScript.AddRange(GetLibraryList(configLibRec.LibraryId));
            }

            // Get Scripts
            List<string> scripts = getScriptTags(LibraryRecsToScript);
            return scripts;
        }

Это затем добавит объект tblLibrary во внешний список с именем librarySeen, и для каждого вызова проверьте, был ли он уже добавлен в librarySeen, чтобы остановить бесконечный цикл.

 private List<TblLibrary> GetLibraryList(int libraryID)
        {
            List<TblLibrary> retVal = new List<TblLibrary>();
            // master list of records found is a class wide variable so that this routine can be called from within itself
            TblLibrary libRec = db.TblLibrary.FirstOrDefault(s=> s.Id == libraryID);

            librariesSeen.Add(libRec);
            if (retVal.Contains(libRec) == false)
            {
                List<TblLibraryRequirements> requirementsFound = db.TblLibraryRequirements.Where(s => s.LibraryId == libraryID).ToList();
                foreach (TblLibraryRequirements req in requirementsFound)
                {
                    TblLibrary reqLibRecord = db.TblLibrary.FirstOrDefault(s => s.Id == req.RequiresId);
                    if (librariesSeen.Contains(reqLibRecord) == false)
                    {
                        retVal.AddRange(GetLibraryList(reqLibRecord.Id));
                    }
                }
                retVal.Add(libRec);

                // Remove Duplicates
                retVal = retVal.Distinct().ToList();
            }
            return retVal;
        }

Надеюсь, это поможет кому-то еще =)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...