Как я могу закодировать рекурсивный поиск связанных объектов базы данных?

#c# #entity-framework #recursion #search

#c# #entity-framework #рекурсия #Поиск

Вопрос:

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

Рассматриваемые таблицы базы данных — это tblLibrary amp; tblLibraryRequirements

Таблица tblLibraryRequirements состоит из следующих столбцов: — 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.

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

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

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

Комментарии:

1. я не уверен, что это хороший подход; вам также нужно будет обратиться к управлению версиями, поскольку один пакет получает новую зависимость, начиная с определенной версии; почему бы просто не разместить статические файлы?

2. Сами файлы размещаются на этом, таблица tblLibrary имеет имя и версию как часть своей схемы. Идея здесь в том, что с помощью пользовательского интерфейса член команды может выбирать нужные библиотеки, и для них генерируются теги скрипта, включая зависимости

Ответ №1:

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

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

  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 будет добавлен во внешний список с именем librariesSeen, и при каждом вызове проверяйте, был ли он уже добавлен в librariesSeen, чтобы остановить бесконечный цикл.

  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;
        }
  

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