Шикарный запрос вложенного списка

У меня есть 3 класса POCO, как показано ниже;

Континент имеет много ContinentPart

На континенте много стран

В стране много городов

Я хочу получить Continens с ContinentParts, Country and Cities

using (IDbConnection db = new SqlConnection(_conf["ConnectionStrings:WorkConStr"]))
            {
                string query = @"SELECT * FROM Continent as c
                                LEFT JOIN ContinentPart as cp ON c.ContinentId=cp.ContinentId
                                LEFT JOIN Country as co ON c.ContinentId=co.ContinentId
                                LEFT JOIN City ci ON co.CountryId=ci.CountryId
                                ORDER BY c.RecDate DESC";

                var continentDictionary = new Dictionary<int, Continent>();
                var list = db.Query<Continent, ContinentPart, Country, City, Continent>(
                    query,
                    map: (continent, continentPart, country, city) =>
                     {
                         Continent m;
                         if (!continentDictionary.TryGetValue(continent.ContinentId, out m))
                         {
                             continentDictionary.Add(continent.ContinentId, m = continent);
                         }
                         if (m.ContinentParts == null)
                             m.ContinentParts = new List<ContinentPart>();
                         m.ContinentParts.Add(continentPart);
                         if (m.Countries == null)
                             m.Countries = new List<Country>();
                         m.Countries.Add(country);
                         foreach (var h in m.Countries)
                         {
                             if (h.Cities == null)
                                 h.Cities = new List<City>();
                             h.Cities.Add(city);
                         }
                         return m;
                     },
                    param: new { },
                    splitOn: "")
                    .Distinct()
                    .ToList();
                return list;
            }

person murat kurtun    schedule 29.04.2018    source источник


Ответы (1)


Здесь у вас есть два варианта. Вы можете использовать функцию множественных наборов результатов:

https://medium.com/dapper-net/handling-multiple-resultsets-4b108a8c5172

Или другой вариант, который, на мой взгляд, лучше, — вернуть объединенный результат в виде JSON, например, с помощью следующего запроса:

select 
    continents.continent_id,
    continents.continent,
    countries.country_id,
    countries.country,
    cities.city_id,
    cities.city 
from 
    dbo.Continent continents
inner join 
    dbo.Country countries on continents.continent_id = countries.continent_id
inner join
    dbo.City cities on countries.country_id = cities.country_id
for 
    json auto

который возвращает JSON следующим образом:

{
    "continent_id": 1,
    "continent": "Africa",
    "countries":
    [
        {
            "country_id": 1,
            "country": "Nigeria",
            "cities":           
            [   
                {
                    "city_id": 1,
                    "city": "Lagos"
                }, {
                    "city_id": 2,
                    "city": "Abuja"
                }
            ]
        }
    ]
}

и затем его можно превратить в сложный объект с помощью обработки пользовательского типа:

https://medium.com/dapper-net/custom-type-handling-4b447b97c620

Ссылки на статьи, которые я написал на эту тему.

person mauridb    schedule 30.04.2018
comment
Привет, спасибо за быстрый ответ, я попробовал первый вариант, и это сработало. Второй немного сложнее. может быть, я попробую позже. Еще один вопрос; что с производительностью? Например, у меня есть таблица счетов, и у нее есть данные во многих таблицах базы данных. он имеет строку 100K. Первый подход эффективен в этом сценарии? - person murat kurtun; 30.04.2018
comment
Вот пример того, как вернуть весь набор континентов, стран и городов в виде одного большого документа json: Код SQL для настройки образца: gist.github.com/yorek/a46c837aacf00d9c58a4f9e8146e7cc0 .NET Core 2.0 Код C#: gist.github.com/yorek/587616768e2a12054403b68762682ace - person mauridb; 02.05.2018
comment
Помимо примера, я бы настоятельно не рекомендовал возвращать 100 000 строк за один проход. Вам действительно нужно загружать все эти данные в память? Вероятно, пострадает производительность. Лучше загрузить только тот континент (или страну, или город), который вам нужен. - person mauridb; 02.05.2018
comment
Привет, я знаю, что у тебя есть важная работа :), но большое спасибо за ответы. Я согласен с вами по поводу проблемы с производительностью, если я получаю 100 000 строк за один проход. А вот мой сценарий о репортажах. Я использую стороннюю сетку для результатов отчета и сортировки или группировки результатов отчета пользователя в памяти, чем отправляю в Excel. В любом случае спасибо за вашу помощь. - person murat kurtun; 03.05.2018
comment
@ adiii4 adiii4 Я думаю, вы имеете в виду рекурсивный CTE, верно? Если да, то должно. Никогда не пытался быть отточенным, но я не понимаю, почему это не должно работать - person mauridb; 18.06.2019
comment
Да, это то, что я пытаюсь сделать. Я пытаюсь создать структуру файлового дерева. - person adiii4; 24.06.2019