如何在NHibernate(而不是FluentNHibernate)中映射此类?
假设我有这样一个数据库: 此设置用于授予角色菜单权限 请注意,如何在NHibernate(而不是FluentNHibernate)中映射此类?,nhibernate,nhibernate-mapping,Nhibernate,Nhibernate Mapping,假设我有这样一个数据库: 此设置用于授予角色菜单权限 请注意,用户-表与权限-表没有直接关系。 那么我应该如何将这个类映射到数据库表呢 class User { public int ID { get; set; } public string Name { get; set; } public string Username { get; set; } public string Password { get; set;
用户
-表与权限
-表没有直接关系。
那么我应该如何将这个类映射到数据库表呢
class User
{
public int ID { get; set; }
public string Name { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public bool? IsActive { get; set; }
public IList<Role> RoleItems { get; set; }
public IList<Permission> PermissionItems { get; set; }
public IList<string> MenuItemKeys { get; set; }
}
类用户
{
公共int ID{get;set;}
公共字符串名称{get;set;}
公共字符串用户名{get;set;}
公共字符串密码{get;set;}
公共bool?IsActive{get;set;}
公共IList角色项{get;set;}
公共IList权限项{get;set;}
公共IList MenuItemKeys{get;set;}
}
这就是说,
(1) 每个用户都有一些角色
(2) 每个用户都有一些权限
s(取决于to角色
s)
(3) 每个用户都有一些允许的MenuItemKey
s(根据Permission
s)
我的User.hbm.xml
应该是什么样子?这里有一个链接:
下面是另一个有用的链接:
编辑
经过一整晚的研究,我得出了以下结论:
考虑到,你想做的是没有好处的李>
不要使用外来关联映射。
真正多对多关联的好用例很少。大多数情况下,您需要存储在“链接表”中的其他信息。在这种情况下,最好对中间链接类使用两个一对多关联。事实上,我们认为大多数关联都是一对多和多对一的,在使用任何其他关联样式时都应该小心,问问自己这是否真的必要
作为一种编程哲学,我更喜欢保持它的简单性,而不是必须编写聪明的代码,即使是我在一段时间后也无法理解我所写的东西李>
另外,我甚至考虑使用关联映射的子查询元素,如果我能找到一种参数化它的方法(如果可行的话),该元素会起作用,但它似乎不允许我用用户实例的Id属性值参数化查询李>
在一个精心设计的OO模型中,一个孩子意识到他父母的财产是很好的,但是一个父母访问一个孩子的财产却没有感觉到设计的味道李>
考虑到上下文公开了用户直接访问权限或MenuItemKey值的好处,我可以理解,我建议以下解决方案:
- 自己创建一个用户定义的数据视图,该视图将保存与通过用户作为成员的角色获得的MenuItemKey权限属性相关的值,如下所示:
将视图UDVuser任务创建为
选择UR.UserID,P.ID作为N'ID',P.MenuItemKey
来自用户U
UR.UserID=U.ID上的内部连接UsersRoles UR
R.ID=UR.RoleID上的内部联接角色R
P.RoleID=R.ID上的内部联接权限P
去
然后,根据User.hbm.xml文件映射它:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="User" table="Users">
<id name="Id" column="ID">
<generator class="identity"/>
</id>
<property name="Name" length="100"/>
<property name="UserName" length="10" not-null="true"/>
<property name="Password" length="10" not-null="true"/>
<property name="IsActive" not-null="true"/>
<list name="Roles" table="UsersRoles" access="private-property" lazy="true">
<key column="UserID" foreign-key="FK_UR_U"/>
<list-index column="UserID"/>
<many-to-many class="Role" column="RoleID" />
</list>
<!-- Here mapping Permissions granted to User. -->
<list name="Permissions" table="udvUsersPermissions" lazy="true">
<key column="UserID"/>
<list-index column="MenuItemKey"/>
<many-to-many column="ID" class="Permission"/>
</list>
</class>
</hibernate-mapping>
在这里,我会让你知道subselect解决方案,以防它以我没有预料到的方式工作
<list name="Permissions" lazy="true">
<subselect> <!-- see section 7.6, Chapter 7 - Association mappings -->
select U.ID, P.ID, P.MenuItemKey
from Users U
inner join UsersRoles UR ON UR.UserID = U.ID
inner join Roles R ON R.ID = UR.RoleID
inner join Permissions P ON P.RoleID = R.ID
group by U.ID, P.ID, P.MenuItemKey
order by P.MenuItemKey
</subselect>
<key column="U.ID"/>
<list-index column="P.MenuItemKey"/>
<many-to-many class="Permission" column="P.ID"/>
</list>
选择U.ID、P.ID、P.MenuItemKey
来自用户U
UR.UserID=U.ID上的内部联接UsersRoles UR
R.ID=UR.RoleID上的内部联接角色R
P.RoleID=R.ID上的内部联接权限P
按U.ID、P.ID、P.MenuItemKey分组
按P.MenuItemKey订购
现在,我希望我带来了足够的细节,这样可以帮助你实现你想做的事情,或者让你走上正轨 角色和权限在应用程序中可能会被大量访问。它们很可能位于二级缓存中,这意味着我们可以有效地迭代User.RoleItems和Role.Permissions
这样做的优点是,在迭代这些集合时,我们通常可以不执行查询
您可以按如下方式映射这些类
属性User.PermissionItems和User.MenuItemKeys是从持久实体派生的,因此不会出现在映射中
<class name="User" table="user">
<id name="ID">
<generator class="native"/>
</id>
<property name="Name"/>
<property name="Username"/>
<property name="Password"/>
<property name="IsActive"/>
<bag name="RoleItems" table="userrole" lazy="true">
<key column="userid" />
<many-to-many class="Role" column="roleid"/>
</bag>
</class>
<class name="Role" table="role">
<id name="ID">
<generator class="native"/>
</id>
<property name="RoleName"/>
<property name="IsActive"/>
<bag name="Permissions" table="permission">
<key column="roleid" />
<one-to-many class="Permission"/>
</bag>
</class>
<class name="Permission" table="permission">
<id name="ID">
<generator class="native"/>
</id>
<property name="MenuItemKey"/>
</class>
我会将用户上的另外两个列表制作成派生枚举。如果它们是列表,则没有明确的方法插入其中,因为您无法知道该值应用于哪个角色。此外,角色不属于用户
更新:现在使用Diego对这些属性的改进版本
class User
{
public virtual IEnumerable<Permission> PermissionItems
{
get {
return RoleItems.SelectMany(role => role.PermissionItems);
}
}
public virtual IEnumerable<string> MenuItemKeys
{
get {
return RoleItems.SelectMany(role => role.PermissionItems,
(role, permission) => permission.MenuItemKey);
}
}
}
类用户
{
公共虚拟IEnumerable权限项
{
得到{
返回RoleItems.SelectMany(角色=>role.PermissionItems);
}
}
公共虚拟IEnumerable MenuItemKey
{
得到{
返回RoleItems.SelectMany(角色=>role.PermissionItems,
(角色,权限)=>permission.MenuItemKey);
}
}
}
拉克兰发布的地图是最好的选择。可以使用对每个集合执行所有联接的查询,但这会使它们仅用于实际目的
但是,有一种更容易实现属性代码的方法,可以帮助您决定:
public IEnumerable<Permission> PermissionItems
{
get
{
return RoleItems.SelectMany(role => role.PermissionItems);
}
}
public IEnumerable<string> MenuItemKeys
{
get
{
return RoleItems.SelectMany(role => role.PermissionItems,
(role, permission) => permission.MenuItemKey);
}
}
public IEnumerable权限项
{
得到
{
返回RoleItems.SelectMany(角色=>role.PermissionItems);
}
}
公共IEnumerable MenuItemKey
{
得到
{
返回RoleItems.SelectMany(角色=>role.PermissionItems,
(角色,权限)=>permission.MenuItemKey);
}
}
为什么不将用户映射到角色,将权限映射到角色。然后使用角色获取权限?一个简单的linq查询:var permissions=user.RoleItems.SelectMany(x=>x.PermissionItems);(或您的计算机上的方法)