Что не так со следующим Быстрым Отображением NHibernate?

У меня есть 3 таблицы (Многие Многим отношения)

  1. Ресурс {ResourceId, описание}
  2. Роль {RoleId, описание}
  3. Разрешение {ResourceId, RoleId}

Я пытаюсь отобразить приведенные выше таблицы в быстром-nHibernate. Это - то, что я пытаюсь сделать.

var aResource = session.Get<Resource>(1); // 2 Roles associated (Role 1 and 2)
var aRole = session.Get<Role>(1);
aResource.Remove(aRole); // I try to delete just 1 role from permission.

Но sql, сгенерированный здесь, (который является неправильным),

Delete from Permission where ResourceId = 1
Insert into Permission (ResourceId, RoleId) values (1, 2);

Вместо (правильный путь)

    Delete from Permission where ResourceId = 1 and RoleId = 1

Почему nHibernate ведут себя как это? Что неправильно с отображением? Я даже попробовал Набором вместо IList. Вот полный код.

Объекты

public class Resource
{
    public virtual string Description { get; set; }
    public virtual int ResourceId { get; set; }
    public virtual IList<Role> Roles { get; set; }

    public Resource()
    {
        Roles = new List<Role>();
    }
}

public class Role
{
    public virtual string Description { get; set; }
    public virtual int RoleId { get; set; }
    public virtual IList<Resource> Resources { get; set; }

    public Role()
    {
        Resources = new List<Resource>();
    }
}

Отображение здесь

// Mapping ..
public class ResourceMap : ClassMap<Resource>
{
    public ResourceMap()
    {
        Id(x => x.ResourceId);
        Map(x => x.Description);
        HasManyToMany(x => x.Roles).Table("Permission");
    }
}

public class RoleMap : ClassMap<Role>
{
    public RoleMap()
    {
        Id(x => x.RoleId);
        Map(x => x.Description);
        HasManyToMany(x => x.Resources).Table("Permission");
    }
}

Программа

    static void Main(string[] args)
    {
        var factory = CreateSessionFactory();
        using (var session = factory.OpenSession())
        {
            using (var tran = session.BeginTransaction())
            {
                var aResource = session.Get<Resource>(1);
                var aRole = session.Get<Role>(1);
                aResource.Remove(aRole);
                session.Save(a);
                session.Flush(); 
                tran.Commit();
            }
        }
    }
    private static ISessionFactory CreateSessionFactory()
    {
        return Fluently.Configure()
            .Database(MsSqlConfiguration.MsSql2008
            .ConnectionString("server=(local);database=Store;Integrated Security=SSPI"))
            .Mappings(m => 
                m.FluentMappings.AddFromAssemblyOf<Program>()
                .Conventions.Add<CustomForeignKeyConvention>())
            .BuildSessionFactory();
    }

    public class CustomForeignKeyConvention : ForeignKeyConvention
    {
        protected override string GetKeyName(FluentNHibernate.Member property, Type type)
        {
            return property == null ? type.Name + "Id" : property.Name + "Id";
        }
    }

Спасибо, Ashraf.

5
задан ashraf 26 March 2010 в 17:16
поделиться

1 ответ

nHibernate считает, что все отношения двунаправленные, пока вы не объявите родительский / дочерний. Поэтому вам нужно "Обратное". Без этого требуется два шага: «Удалить» все и «Восстановить» с новым значением, особенно с типом «Сумка» (по умолчанию). Для ManyToMany изменение типа коллекции сущностей (HashSet / Set) не повлияет на сопоставление с «Bag». Это работает только для HasMany. Вам нужно конкретно сказать «AsSet» на карте. (IList / ICollection) сопоставляется с «Сумкой». Если вы хотите List, вам нужно иметь его «AsList» на карте. Но List требует дополнительного столбца индекса в таблице.

// Mapping .. 
public class ResourceMap : ClassMap<Resource> 
{ 
    public ResourceMap() 
    { 
        Id(x => x.ResourceId); 
        Map(x => x.Description); 
        HasManyToMany(x => x.Roles).AsSet().Inverse().Table("Permission");
    } 
} 

public class RoleMap : ClassMap<Role> 
{ 
    public RoleMap() 
    { 
        Id(x => x.RoleId); 
        Map(x => x.Description); 
        HasManyToMany(x => x.Resources).AsSet().Cascade.SaveUpdate().Table("Permission");
    } 
} 

Кроме того, я бы поместил Fetch.Select (). LazyLoad () для отложенной загрузки.

6
ответ дан 14 December 2019 в 13:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: