Несколько объектов, совместно использующих одну и ту же таблицу отношений ролей - PullRequest
1 голос
/ 08 ноября 2011

Пытаясь придерживаться принципов СУХОГО, будет ли следующий способ иметь несколько объектов с общей таблицей отношений ролей.

Если у нас есть следующие типы (созданные исключительно для этого примера):

class User
{
    ...
}

class Article
{
    ...
}

Для обоих этих объектов должны быть определены роли против них. Таким образом, Роль не уникальна ни для одного из этих объектов.

Моя идея заключалась в том, чтобы репозитории выполняли операции CRUD над этими объектами, а также позволяли Role иметь свой собственный репозиторий, доступ к которому возможно через службу?

Репозитории будут передавать UserDTO и ArticleDTO в класс Builder, который будет производить необходимые объекты Domain. В этом случае:

class User
{
    ...
    IList<Role> Roles { get; set; }
    //Other Domain objs/logic
}

class Article
{
    ...
    IList<Role> Roles { get; set; }
    //Other Domain objs/logic
}

Объект Role будет иметь таблицу Role:

ИД

И таблица отношений:

itemId roleId itemType

построитель ролей / служба, используемая для прикрепления ролей к объекту домена, может выглядеть примерно так:

static class RoleBuilder
{
    IEnumerable<Role> Fetch(int id, typeof(obj))
    {
        //fetch from RoleRep
    }

    bool Save(IEnumerable<Role>, int id, typeof(obj))
    {
        //save through role rep
    }
}

Что-то не так с этой идеей? например:

public static UserBuilder
{
    public User FetchUser(int id)
    {
        //map userDTO to user
        var user = map...

        //populate roles
        if(user != null)
            user.Roles = RoleBuilder.Fetch(id, typeof(user));
    }
}

Альтернатива состоит в том, чтобы пользователь и статья управляли своими собственными манипуляциями с ролями и, возможно, имели несколько таблиц ролевых отношений, например user_has_roles, article_has_roles

Первое решение позволило бы конечным пользователям также изменять роли (переименовывать, добавлять новые роли и т. Д.), Не повреждая модель домена, тогда как во втором решении я не уверен, как это сделать чисто (обновите их через пользователь, через статью?)

Ответы [ 3 ]

1 голос
/ 08 ноября 2011

Если концепция ролей отделена от пользователя и статьи, что звучит так, как будто она применяется к обоим объектам домена, то я бы, вероятно, смоделировал модель, как вы предлагаете.

Я не уверен, что вы имеете в виду, когда говорите «разрешить изменение ролей и конечному пользователю». Если роли представляют собой отдельную концепцию, они, вероятно, должны иметь свои собственные доменные классы для представления операций, которые можно выполнять с ролями (переименование, удаление и т. Д.).

Кроме того, ваш фрагмент кода, вероятно, должен выглядеть следующим образом (с использованием обобщений вместо недопустимого синтаксиса typeof () в приведенном выше фрагменте):

static class RoleBuilder {
    static IEnumerable<Role> Fetch<T>(int id) {
        switch(typeof(T)) { ... }
    }

    static bool Save<T>(IEnumerable<Role> roles, int id) {
        switch(typeof(T)) { ... }
    }
}

Возможно, я бы также подумал о том, чтобы иметь какой-то базовый класс для всех объектов домена, которым могут быть назначены роли (если роли используются для безопасности, то, возможно, SecurableEntity или что-то в этом роде), тогда вы можете иметь таблицу базовых классов в БД для поддержка общих идентификаторов для идентификаторов (чтобы вы могли избавиться от столбца itemType в таблице ролей). В качестве альтернативы вы можете просто использовать GUID для идентификаторов сущностей, что значительно упрощает многие вещи.

0 голосов
/ 08 ноября 2011

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

0 голосов
/ 08 ноября 2011

Ваша идея звучит хорошо. Я бы старался не связывать роли (или, более общие, некоторые системы авторизации) со статьями и моделями пользователей.

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

Другая проблема может возникнуть из-за вашей реализации UserBuilder. Для выборки одного пользователя, который может быть в порядке, но выборка нескольких пользователей с этой логикой приведет к выбору N + 1.

...