Создайте запрос объединения групп LINQ для структуры сущностей, чтобы получить подмножество свойств из DTO и список другого ядра DTO, ASP.net. - PullRequest
1 голос
/ 04 октября 2019

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

Прошу прощения за мою новизну в SO (считайте, что это начало моей репутации), дайте мне знать, если я сделаю что-нибудь неправильно или что-нибудь забуду.

Я пытаюсь:

  1. Создание контроллера, который запрашивает базу данных для всех пользователей и их ролей.
  2. Возвращает список уникальных идентификаторов пользователей и адрес электронной почты со списком ролей.
  3. Электронная почтаадрес и роли находятся в отдельных таблицах, а pkey / fkey - это идентификатор пользователя
  4. . Роли возвращаются в виде списка, содержащего мой AllUserInRolesDto

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

Вот мой DTO

namespace Lib.Dtos
{
    public class AllUserInRolesDto
    {
        public string FullName { get; set; }
        public string Email { get; set; }
        public List<RoleDto> Roles { get; set; }
    }

    public class RoleDto
    {
        public string RoleName { get; set; }
    }

}

Iесть бизнес-уровень, который определяет запрос LINQ

public List<AllUserInRolesDto> UserAllRolesGet()
{
    List<AllUserInRolesDto> getAllUsersRoles = (from u in _context.Users
                            join r in _context.UserInRoles on u.UserId equals r.UserId
                            into ur
                            select new Lib.Dtos.AllUserInRolesDto()
                            {
                                FullName = u.Fullname,
                                Email = u.Email,
                                Roles = ur //this was the problem line and what the docs were describing
                            }).ToList();

    return getAllUsersRoles;
}

... и мой контроллер

[HttpGet("GetAllUserRolesList")]
public IActionResult GetAllUserRolesList()
{
    List<Lib.Dtos.AllUserInRolesDto> allUsers = _userBL.UserAllRolesGet();
    return new JsonResult(allUsers);
}

мое решение

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

public List<AllUserInRolesDto> UserAllRolesGet()
{
    List<AllUserInRolesDto> getAllUsersRoles = (from u in _Context.Users
                            join r in _context.UserInRoles on u.UserId equals r.UserId
                            into ur
                            select new Lib.Dtos.AllUserInRolesDto()
                            {
                                FullName = u.Fullname,
                                Email = u.Email,
                                Roles = .Select(x => new Lib.Dtos.RoleDto() { RoleName = x.RoleName }).ToList() //Changed to this
                            }).ToList();

    return getAllUsersRoles;
}

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

1 Ответ

0 голосов
/ 04 октября 2019
  • Я предполагаю, что вы используете Entity Framework и что ваша модель БД определена с помощью отношений. Это означает, что вам не нужно использовать явные соединения в своих запросах: вместо этого вы можете использовать свойства навигации.
  • Ваш «бизнес-уровень» (обратите внимание, что бизнес-уровень не всегда нужен) должен работать толькос типами сущностей и не должны использовать DTO (поскольку DTO принадлежат вашему веб-сервису так же, как View-Models принадлежат веб-приложению).
    • Если ваш «бизнес-уровень» состоит только из предопределенных запросов, я рекомендую определять их как статические методы расширения для вашего DbContext и возвращать IQueryable<T> вместо материализованного List<T>, поскольку это позволяет вашим потребителям выполнятьдальнейшие операции над ними (такие как дополнительная фильтрация или сортировка и разбиение на страницы).

Я рекомендую делать это следующим образом:

// Queries methods (i.e. "business layer" queries)
public static class QueriesExtensions
{
    public static IQueryable<User> GetAllUsersAndTheirRoles( this MyDbContext db )
    {
        // I assume `UserInRoles` is a linking table for a many-to-many relationship:
        return db
            .UserInRoles
            .Include( uir => uir.User )
            .Include( uir => uir.Role )
            .Select( uir => uir.User );
    }
}

// Web-service controller:
[HttpGet("GetAllUserRolesList")]
[Produces(typeof(List<AllUserInRolesDto>)]
public async Task<IActionResult> GetAllUserRolesList()
{
    List<User> usersList = await this.db
        .GetAllUsersAndTheirRoles()
        .ToListAsync();

    List<Lib.Dtos.AllUserInRolesDto> usersListDto = usersList
        .Select( u => ToDto( u ) )
        .ToList();

    return new JsonResult( usersListDto  );
}

// Entity-to-DTO mapping functions (if you have a lot of DTOs and entities, consider using AutoMapper to reduce the tedium)
private static AllUserInRolesDto ToDto( User user )
{
    return new AllUserInRolesDto()
    {
        FullName = user.FullName,
        Email    = user.Email,
        Roles    = user.Roles.Select( r => ToDto( r ) ).ToList()
    };
}

private static RoleDto ToDto( Role role )
{
    return new RoleDto()
    {
        RoleName = role.RoleName
    };
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...