我有 3 个表(多对多关系)
我试图在 fluent-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 表现得像这样?映射有什么问题?我什至尝试使用 Set 而不是 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";
}
}
谢谢,
阿什拉夫。
最佳答案
nHibernate 认为所有关系都是双向的,直到你声明父/子。所以你需要“反向”。没有它,它需要两个步骤,即“全部删除”和“使用新值重新创建”,尤其是“包”类型(默认)。对于 ManyToMany,更改实体集合类型(HashSet/Set)不会影响到“Bag”的映射。它仅适用于 HasMany。您需要在 map 中特别说“AsSet”。 (IList/ICollection) 映射到“包”。如果你想要列表,你需要在 map 中拥有“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() 用于延迟加载。
关于asp.net-mvc - 以下 Fluent NHibernate Mapping 有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2520607/