2016-08-24 2 views
0

Я строю обычную ОРМ, используя Dapper. У меня есть следующие таблицы:- это элегантный способ реализовать этот сценарий ассоциации в пользовательском orm?

  • пользователя
  • Роль
  • Разрешение
  • RolePermission

Мой sproc имеет 2 выбирает: 1 для базовой информации о пользователе, 1 для пользователя роли информации. Основная информация пользователя десериализуется в пользовательский объект. Информация RolePermission десериализуется в пользовательский объект RolePermission и затем программно ассоциируется с объектом User. Насколько сложно было бы реализовать реализацию графика объекта в пользовательской ORM? Например, EF берет хороший и простой подход OO, чтобы получить имя роли следующим образом: User.UserRoles.Role.Name. Однако это достигается за счет использования сложного и сложного f/w, который автоматически отображает объединение объектов на основе ассоциаций db fk. Это также связано с производительностью. Моя мысль создать мои классы сущностей следующим образом:

  • MyCompany.Entities.Entity.User.User
  • MyCompany.Entities.Entity.User.RolePermission

Поэтому мой объект RolePermission бы полностью адаптированы к объекту User без внешних зависимостей. Это позволило бы объекту RolePermission максимально облегчить работу в контексте объекта User. Для поддержки других объектов/доменов/обычаев не нужны никакие дополнительные свойства. Это кажется элегантным (простым, эффективным, эффективным) решением. Каковы ваши мысли об этом типе подхода для создания сложного объекта в пользовательском ORM?

ответ

0

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

Итак, во-первых: вы запрашиваете пользователей (неглубокие) и необязательно детали пользователя, включая информацию о роли (глубину).

public IEnumerable<User> GetUsers(int? userID, bool withDetails) 
     { 
      var users = db.Query<User>(@" select * 
              from dbo.Users u 
              where (@userID IS NULL OR u.Id = @userID)", new { userID }); 

      if (withDetails) 
      { 
       var rolePermissions = db.Query<RolePermission>(@" select * 
                    from dbo.RolePermissions rp 
                    where rp.UserId IN (select val from dbo.udf_ConvertIntListToTable(@userId_list))", new { userId_list = String.Join(',', users.Select(s => s.UserId)) }); 
       foreach(var user in users) 
       { 
        user.RolePermissions = rolePermissions.Where(w => w.UserId == user.UserId); 
       } 
      } 
     } 

Несколько замечаний:

  • dbo.udf_ConvertIntListToTable очень хорошо установлены и выполняет большой. Найдите в Интернете, и вы его найдете. Я загружу его как сущность, если вы не сможете его найти.
  • RolePermission должен иметь ссылку на внешнего пользователя (я использовал UserId). Кроме того, этот запрос, скорее всего, отобразит дополнительные данные, которые вы упомянули (например, Роль, Разрешение и т. Д.)
  • У меня есть тонны расширений, которые убирают выше. Я держал его как можно более сырым, чтобы вы могли видеть, что происходит.
  • У вас теперь есть очень легкий запрос (withDetails = false) для списков и т. Д., А более тяжелый запрос со всеми данными, красиво завернутыми в его совокупный корень (Пользователь).
Смежные вопросы