NHibvernate 3.2 многие ко многим не заполняют таблицы соединений - PullRequest
2 голосов
/ 31 марта 2012

У меня есть два класса, пользователь и роль, определенные как:

public class User : Entity
{
    // other properties ...
    public virtual string Username
    public virtual ICollection<Role> Roles { get; set; }
}

public class Role : Entity
{
    public virtual string Name { get; set; }
    public virtual ICollection<User> Users { get; set; }
}

В коде отображения у меня есть следующее:

mapper.Class<User>(map =>
{
    map.Bag(x=>x.Roles,
        cm=>
        {
            cm.Table("UserRole");
            cm.Cascade(Cascade.All);
            cm.Key(k => k.Column("[User]"));
        },
        em=>
        {
            em.ManyToMany(mm =>
            {
                mm.Column("[Role]");
            });
        });

});

mapper.Class<Role>(map =>
{
    map.Bag(x=>x.Users, 
        cm=>
        {
            cm.Inverse(true);
            cm.Table("UserRole");                        
            cm.Key(k=>k.Column("[Role]"));
        },
        em =>
        {
            em.ManyToMany(mm =>
            {
                mm.Column("[User]");
            });
        });
});

Отображения генерируют ожидаемую схему, но таблица соединений никогда не заполняется. Добавление нового пользователя с новой ролью в его коллекции сохраняет роль, а затем пользователя в соответствующих таблицах, но таблица соединения остается пустой. Почему?

Редактировать: Я до сих пор не сделал никакого прогресса в этом. Я абсолютно уверен, что отображение правильное, и генерируется правильная схема, но таблица соединений просто не заполняется. В целях тестирования я создаю сущности, используя NBuilder, например:

var roles = new Role[] 
{
    new Role("Admin"),
    new Role("Manager"),
    new Role("User")
};

var users = Builder<User>.CreateListOfSize(10)
    .TheFirst(1)
        .Do(x =>
            {
                x.Roles.Add(roles[0]);
                x.Roles.Add(roles[1]);
                roles[0].Users.Add(x);
                roles[1].Users.Add(x);
            })
    .All()
        .With(x => x.Id = 0)
        .And(x => x.Version = 0)
        .And(x => x.Username = "test user")
        .And(x => x.Password = "test password")
        .Do(x => 
        {
            x.Roles.Add(roles[2]);
            roles[2].Users.Add(x);
        }
    .Build();


foreach (var u in users) session.Save(u);

Объекты Пользователь и Роль сохраняются правильно, но таблица соединений остается пустой. Это означает, что я не могу эффективно запросить роли для данного пользователя позже, что сводит на нет точку.

Ответы [ 2 ]

1 голос
/ 01 апреля 2012

Убедитесь, что оба класса ссылаются друг на друга.

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

role.Users.Add(user);    
user.Roles.Add(role);

session.Save(user); // NH only saves user and role, so it can get auto-generated identity fields
session.Flush(); // NH now can save into cross-ref table, because it knows required information (Flush is also called inside of Transaction.Commit())

Я нашел хорошийответ на вопрос «многие ко многим» с множеством объяснений и цитат из документации NH.Я думаю, что это стоит прочитать.

[РЕДАКТИРОВАТЬ]

В ответ на этот несколько похожий вопрос, в котором обсуждается необходимость явной транзакции для сохранения в перекрестномупоминается таблица.

Я также отредактировал код выше с добавлением session.Flush(), чтобы отразить мои выводы.

0 голосов
/ 01 апреля 2012

Я закончил тем, что скачал источник NHibernate и сослался на него напрямую, чтобы я мог пройти через него. Оказывается, это было связано с тем, что мой код для генерации тестовых данных не был включен в явную транзакцию сеанса. Как только я добавил это, это было хорошо. Я хотел бы увидеть какое-то объяснение этому, поскольку я не смог четко следовать коду, но я по крайней мере удовлетворен тем, что проблема решена.

...