Отображение списка перечислений

У меня есть таблица под названием UserPermissions с FK для таблицы пользователей по userId, а затем строковый столбец для строкового значения перечисления.

Я вижу ошибку NHibernate.MappingException: ассоциация из таблицы UserPermissions относится к несопоставленному классу: GotRoleplay.Core.Domain.Model.Permission.

Мое перечисление разрешений:

    public enum Permission
{
    [StringValue("Add User")]
    AddUser,

    [StringValue("Edit User")]
    EditUser,

    [StringValue("Delete User")]
    DeleteUser,

    [StringValue("Add Content")]
    AddContent,

    [StringValue("Edit Content")]
    EditContent,

    [StringValue("Delete Content")]
    DeleteContent,
}

Свойство в моем классе User:

public virtual IList<Permission> Permissions { get; set; }

Моя таблица базы данных:

CREATE TABLE dbo.UserPermissions
(
UserPermissionId            int                 IDENTITY(1,1) NOT NULL,
UserId                      int                 NOT NULL,
PermissionName              varchar (50)        NOT NULL,

CONSTRAINT PK_UserPermissions PRIMARY KEY CLUSTERED (UserPermissionId),
CONSTRAINT FK_UserPermissions_Users FOREIGN KEY (UserId) REFERENCES Users(UserId),
CONSTRAINT U_User_Permission UNIQUE(UserId, PermissionName)
)

Моя попытка сопоставить свойство разрешений моего пользовательского объекта:

HasManyToMany(x => x.Permissions)
             .WithParentKeyColumn("UserId")
             .WithChildKeyColumn("PermissionName")
             .WithTableName("UserPermissions")
             .LazyLoad();

Что я делаю не так, что он не может сопоставить разрешение со списком значений перечисления?


person Josh    schedule 23.05.2009    source источник
comment
Итак, после долгой работы мне пришлось создать новый объект с именем UserPermission и сопоставить его с таблицей UserPermissions со свойством Permission, используя мое перечисление в качестве типа данных. Это работает нормально, но разрешения могут быть привязаны к ролям и пользователям, то есть мой запрос выбора для получения КАЖДОГО разрешения, назначенного пользователю (включая все его роли), требует сложного набора операторов linq. Я бы предпочел не делать этого. У кого-нибудь есть идеи?   -  person Josh    schedule 27.05.2009


Ответы (3)


вот способ, который сработал для меня

HasMany(x => x.Licences)
                .WithTableName("DriverLicence")
                .AsElement("Level").AsBag();

дополнительную информацию см. здесь ответ

person dbones    schedule 14.09.2009
comment
Спасибо за ваш пост. Я попробую! - person Josh; 15.09.2009

Вам необходимо указать тип, чтобы NHibernate мог преобразовать значение в таблице в член перечисления Permission.

HasManyToMany(x => x.Permissions)
         .WithParentKeyColumn("UserId")
         .WithChildKeyColumn("PermissionName")
         .WithTableName("UserPermissions")
         .LazyLoad()
         .CustomTypeIs(typeof(Permission));

Отредактировано для добавления: Извините, я должен был заметить, что у вас это ManyToMany. Это невозможно: у вас не может быть коллекции Users (другая сторона m: m), свисающей с перечисления. Вам нужно определить это как 1: m или создать таблицу разрешений и класс и сопоставить их как m: m.

person Jamie Ide    schedule 23.05.2009
comment
Я попытался использовать ваше предложение, но CustomTypeIs не существует в качестве допустимого варианта. Я попытался вместо этого использовать .CollectionType (typeof (Permission)), но все еще вижу ту же ошибку: ассоциация из таблицы UserPermissions относится к несопоставленному классу: GotRoleplay.Core.Domain.Model.Permission - person Josh; 24.05.2009

Я думал, что выложу код, который выбрал для своего решения. Это всего лишь обходной путь. Я бы хотел, чтобы Fluent поддерживал списки Enum, но пока это не произойдет, вот возможное решение:

The Enum - это мое перечисление, ваше стандартное перечисление.

public enum PermissionCode
{
    //site permissions 1-99
    ViewUser = 1,

    AddUser = 2,

    EditUser = 3,

    DeleteUser = 4
}

Затем у меня есть класс разрешений.

public class Permission
{
    public virtual int PermissionId { get; set; }
    public virtual string PermissionName { get; set; }

    public virtual PermissionCode PermissionCode 
    {
        get
        {
            return (PermissionCode)PermissionId;
        }
    }
}

Как видите, у меня есть идентификатор и имя, а затем свойство, которое преобразует идентификатор в мое перечисление PermissionCode.

Отображение выглядит так:

public class PermissionMap : ClassMap<Permission>
{
    public PermissionMap() 
    {
        WithTable("Permissions");

        Id(x => x.PermissionId).GeneratedBy.Identity();

        Map(x => x.PermissionName);
    }
}

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

Моя структура таблицы за отображением выглядит так:

CREATE TABLE dbo.Permissions
(
    PermissionId                    int                 NOT NULL,
    PermissionName                  varchar (50)        NOT NULL,

    CONSTRAINT PK_Permissions PRIMARY KEY CLUSTERED (PermissionId)
)

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

person Josh    schedule 14.09.2009