Файл сопоставления XML для связи «многие ко многим» с NHIbernate.

У меня есть таблица User, поля: Id, Username

У меня есть таблица UserGroup, поля: Id, UsergroupName, Code

Я хотел бы назначить несколько групп пользователей по пользователю, это означает, что у меня должна быть третья таблица с: UserId и UsergroupId, эта таблица называется UsersGroups

Я пробовал этот код:

Пользовательская таблица, XML:

<bag name="UsersGroups" generic="true" cascade="all" inverse="false" table="UsersGroups" >
    <key column="UserId" />
    <many-to-many column="GroupId" class="LookupUserGroup" />
</bag>

Пользовательская таблица, С#:

public virtual IList<UserGroup> UsersGroups { get; set; }

Групповая таблица, С# (ничего в отображении XML):

public virtual User User { get; set; }

Чтобы добавить группу пользователю, я использую AddGroup в классе User, я делаю это:

public virtual void AddGroup(UserGroup userGroup)
{
    userGroup.User = this;
    UsersGroups.Add(userGroup); 
}

Когда я делаю запрос для пользователя, я хотел бы использовать linq для проверки поля «Код» следующим образом:

var res = (from c in MyUserList where c.UserGroup.Code == 1 select c);, но поле USergroup недоступно в intellisense.

Любая идея ?

Спасибо,


person Kris-I    schedule 21.03.2011    source источник
comment
Если в группе есть только один пользователь, на которого она ссылается, не является ли это отношением «один ко многим»?   -  person Vadim    schedule 21.03.2011


Ответы (2)


Во-первых, дизайн ваших классов C# кажется неправильным. Они отражают не ваше намерение иметь отношение «многие ко многим», а отношение «один ко многим». Поскольку обычно не имеет смысла разрешать только одному пользователю в группе, вам следует изменить класс UserGroup на

public class UserGroup
{
    [...]

    public virtual IList<User> Users { get; set; }
}

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

<bag name="Users" table="UsersGroups" lazy="true" cascade="all" inverse="true" >
    <key column="GroupId"></key>
    <many-to-many column="UserId" class="User" />
</bag>

Правилен ли класс LookupUserGroup? В этом простом случае отношения «многие ко многим» у вас должно быть только два класса для трех таблиц. Если у вас есть класс User и класс UserGroup, избавьтесь от класса LookupUserGroup и замените его в отображении в User.hbm.xml.

Тогда метод AddGroup в вашем классе User будет выглядеть примерно так:

public virtual void AddGroup(UserGroup userGroup)
{
    if(!this.UsersGroups.Contains(userGroup))
    {
         this.UsersGroups.Add(userGroup);
         userGroup.Users.Add(this); 
    }
}

Причина, по которой intellisense не предлагает поле UserGroup, заключается просто в том, что у вас нет такого поля. Поле называется UsersGroups (должно быть UserGroups) и представляет собой IList<UserGroup>.

К сожалению, текущий провайдер Linq в NHibernate 3.0 на самом деле не поддерживает тот запрос, который вы пытаетесь выполнить здесь. Вместо этого вы можете попробовать использовать QueryOver. В вашем случае это будет выглядеть так (адаптировано из NHibernate QueryOver with ManytoMany)

var result = Session.QueryOver<User>()
    .Right.JoinQueryOver<UserGroup>(x => x.UserGroups) // the .Right. might not be required
    .Where(c => c.Code == 1)
    .List();

Я ничего из этого не реализовывал и не тестировал, поэтому могут быть небольшие ошибки.

person Florian Lim    schedule 21.03.2011

Крис, короткая заметка о вашем дизайнерском решении. Если вы действительно хотите иметь настоящие отношения «многие ко многим», вам не нужен третий объект (UserGroup). Вам нужны только пользователи и группы объектов. Nhibernate самостоятельно создаст промежуточную таблицу. Но я никогда не использую этот подход. Подход, который вы выбрали (с сущностью группы пользователей), мне нравится гораздо больше, потому что он дает вам дополнительную гибкость. Вы никогда не знаете, когда потребуется дополнительная информация об отношениях между пользователями и группами (дата добавления пользователя в группу, кто создал эту связь и т. д.). Поэтому я бы использовал сущность UsersGroups, но то, как вы создаете отношения, — это отношение «многие к одному» между пользователем и группами пользователей, а также отношение «многие к одному» между группой и группами пользователей. Таким образом, вы получаете то, что хотите, с дополнительной гибкостью.

person zszep    schedule 21.03.2011