Использование dapper с JOIN - PullRequest
       19

Использование dapper с JOIN

4 голосов
/ 19 марта 2019

У меня есть запрос с несколькими объединениями, такими как:

var sqlFindByProviderNameAndProviderSubjectId = $@"
     SELECT u.*, la.*, p.*, cp.*, scr.*, lm.*, wm.*
     FROM [user].[User] u
     LEFT JOIN [user].[LinkedAccount] la ON u.Id = la.UserId
     LEFT JOIN [user].[PatientProfile] p ON u.Id = p.UserId
     LEFT JOIN [user].[CareProviderProfile] cp ON u.Id = cp.UserId                
     LEFT JOIN [user].[Screening] scr ON u.Id = scr.UserId
     LEFT JOIN [user].[LengthMeasurement] lm ON scr.Id = lm.ScreeningId
     LEFT JOIN [user].[WeightMeasurement] wm ON scr.Id = wm.ScreeningId                 
                WHERE u.Id = (
                    SELECT UserId
                    FROM [user].[LinkedAccount] la
                    WHERE la.ProviderName = @ProviderName AND la.ProviderSubjectId = @ProviderSubjectId)";

Я использую dapper для дематериализации таблиц в строго типизированные сущности, такие как:

await UnitOfWork.Connection.QueryAsync<User, LinkedAccount, PatientProfile, CareProviderProfile, Screening, LengthMeasurement, WeightMeasurement, User>(query,
    (u, la, p, cp, scr, lm, wm) =>
    {
        // mapping code here
    }

Это отлично работает.

Однако мне нужно добавить еще один JOIN к запросу, но, к сожалению, QueryAsync <> принимает максимум 7 параметров / типов, а у меня больше.

Есть ли другой способ сопоставить несколько таблиц из JOIN в сущности?

Ответы [ 2 ]

3 голосов
/ 19 марта 2019

Dapper не заботится о ваших объединениях, а Dapper заботится о табличной структуре. Каркас по умолчанию использует столбец идентификатора или пользовательский SplitOn для анализа табличной структуры в объект. Итак, табличная структура выглядит следующим образом:

Tabular:
Id | A | Id | B | Id | C | Id | D | Id | E | Id | F | Id | G | Id | H

Вы говорите Dapper, что существует восемь сущностей, Dapper делает это с помощью столбца id. Теперь, если у вас есть сущность, но она не требует абстрагирования таким образом, например, A, B и C должны быть в единой сущности, вы можете сказать Dapper не создавать для них отдельную сущность, выполнив следующее структура.

Tabular:
Id | A | B | C | Id | D | Id | E | Id | F | Id | G | Id | H

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

Основываясь на таблицах данных, я предполагаю, что вы можете объединить пару без потери деловых намерений. Решение, основанное на разделении, решит вашу проблему, в противном случае я не уверен, как вы превысите функциональность семи разделений, встроенных в Dapper.

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

Так вот, что я в итоге и сделал.

Мой основной запрос возвращает только пользователей, связанные учетные записи и профиль:

var sqlFindByProviderNameAndProviderSubjectId = $@"
            SELECT u.*, la.*, p.*, cp.*
            FROM [user].[User] u
            LEFT JOIN [user].[LinkedAccount] la ON u.Id = la.UserId
            LEFT JOIN [user].[PatientProfile] p ON u.Id = p.UserId
            LEFT JOIN [user].[CareProviderProfile] cp ON u.Id = cp.UserId                
            WHERE u.Id = (
                SELECT UserId
                FROM [user].[LinkedAccount] la
                WHERE la.ProviderName = @ProviderName AND la.ProviderSubjectId = @ProviderSubjectId)";

Прикладной уровень может указывать логическое значение IncludeScreening, и, если оно истинно, я также делаю второй вызов для получения информации о проверке:

var sqlFindScreeningForUser = $@"
                SELECT scr.*, lm.*, wm.*, n.*
                FROM [user].[Screening] scr                
                LEFT JOIN [user].[LengthMeasurement] lm ON scr.Id = lm.ScreeningId
                LEFT JOIN [user].[WeightMeasurement] wm ON scr.Id = wm.ScreeningId
                LEFT JOIN [user].[Note] n ON scr.Id = n.ScreeningId
                WHERE scr.UserId = @UserId";

... и полученный Screening затем устанавливается на пользователя.

...