беглый nhibernate - сопоставление «многие ко многим» с атрибутом - PullRequest
1 голос
/ 17 февраля 2011

У меня есть 2 мастер-таблицы, которые связаны таблицей карт, как показано ниже

User [UserId,Name]

Resource [ResourceId,Name]

UserResourceMap [UserId,ResourceId,AccessLevel]

Как будет выглядеть таблица ресурсов и пользователей с AccessLevel в качестве атрибута ресурса?

Классы моего домена выглядят так

public class User
{
    public virtual int UserId { get;protected set; }
    public virtual string Name { get;set; }
}
public class Resource
{
    public virtual int ResourceId { get;protected set; }
    public virtual string Name { get;set; }
    public virtual string AccessLevel { get;set; }//Issue-populate this using fluent
}

Как я могу использовать свободный для сопоставления атрибута accessLevel в коде ниже.

public class UserMap : ClassMap<User>
    {
        public UserMap()
        {
            Table("User");
            Id(x => x.Key);
            Map(x=>x.Name);
        }
    }

public class ResourceMap : ClassMap<Resource>
    {
        public ResourceMap()
        {
            Table("Resource");
            Id(x => x.Key);
            Map(x=>x.Name);//Need some Map Here to make a hasManyToMany Map with attribute
        }
    }

Ответы [ 2 ]

7 голосов
/ 17 февраля 2011

Ваша модель домена, кажется, не соответствует вашей модели базы данных - класс Resource имеет свойство AccessLevel (т.е. один AccessLevel на ресурс), но в модели DB AccessLevel представляет собой столбец в таблице карты (т. Е. Один AccessLevel на пользовательский ресурс).отношение).

Если предположить, что модель БД является правильной моделью, то один (довольно простой) способ сопоставления состоит в том, чтобы ввести такой класс.

public class UserResource {

  public virtual int UserResourceId { get; protected set; }
  public virtual User User { get; set; }
  public virtual Resource { get; set; }
  public virtual string AccessLevel { get; set; }
}

и отобразить его таким образом:

public class UserResourceMap : ClassMap<UserResource> {

  public UserResourceMap() {

    Table("UserResourceMap");
    Id(x => x.UserResourceId);
    References(x => x.User).UniqueKey("UniqueUserAndResource");
    References(x => x.Resource).UniqueKey("UniqueUserAndResource");
    Map(x => x.AccessLevel);
  }
}

Если вы хотите двунаправленные ассоциации, вы также можете добавить свойство Collection в User и / или Resource и сопоставить их с HasMany (...). Inverse ().Конечно, этот тип сопоставления привел бы к появлению нового столбца UserResourceId в таблице UserResourceMap (использование составного ключа, состоящего из User и Resource, уменьшило бы это).

Другим решением будет добавление ассоциации EntityMap.Если ассоциация принадлежит пользователю, это будет словарьимущество.Нечто подобное может сработать:

public class User {
  public virtual int UserId { get; protected set; }
  public virtual string Name { get; set; }
  public virtual Dictionary<Resource, string> Resources { get; set; } // Resource -> AccessLevel
}

public class UserMap : ClassMap<User> {

  public UserMap() {

    Table("User");
    Id(x => x.UserId);
    Map(x => x.Name);
    HasMany<Resource, string>(x => x.Resources).AsEntityMap().Element("AccessLevel");
  }
}
5 голосов
/ 17 февраля 2011

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

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

Как насчет этого:

public class User
{
    public virtual int Id { get;protected set; }
    public virtual string Name { get;set; }
    public virtual ICollection<UserResource> UserResources { get; set;}
}

public class UserResource
{
    public virtual int Id { get; protected set; }
    public virtual User User { get; set;}
    public virtual Resource Resource { get; set;}
    public virtual string AccessLevel { get; set;}
}

public class Resource
{
    public virtual int Id { get;protected set; }
    public virtual string Name { get;set; }
}

И сопоставления типа:

public class UserMap : ClassMap<User>
{
    public UserMap()
    {
        Id(x => x.Id);
        Map(x => x.Name);
        HasMany(x => x.UserResource)
            .AsSet()
            .Inverse()
            .Cascade.AllDeleteOrphan();
    }
}

public class UserResourceMap : ClassMap<UserResource>
{
    public UserResourceMap()
    {
        Table("UserResourceMap");
        Id(x => x.Id);
        References(x => x.User).Not.Nullable();
        References(x => x.Resource).Not.Nullable();
        Map(x => x.AccessLevel);
    }
}

public class ResourceMap : ClassMap<Resource>
{
    public ResourceMap()
    {
        Cache.ReadOnly();

        Id(x => x.Id);
        Map(x => x.Name);
    }
}
...