我的设置非常简单:
public class Role
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual ISet<Permission> Permissions { get; set; }
public Role()
{
Permissions = new HashSet<Permission>();
}
}
public enum Permission
{
ACCESS_USER_MANAGER, [... and many more]
}
根据映射文件:
<class entity-name="UserManager.Model.Role" table="roles">
<id name="Id" type="int">
<generator class="identity" />
</id>
<property name="Name" column="name" type="string"/>
<set name="Permissions" table="permissions">
<key column="role"/>
<element column="name" type="string"/>
</set>
</class>
但是,当我尝试创建一个角色并保存它时:
[TestMethod]
public void TestRoles()
{
ITransaction transaction = _session.BeginTransaction();
Role role = new Role();
role.Name = "Test-Role";
role.Permissions.Add(Permission.ACCESS_USER_MANAGER);
_session.Save(role);
transaction.Commit();
}
我得到一个例外:
System.InvalidCastException:无法将“UserManager.Model.Role”类型的对象强制转换为“System.Collections.IDictionary”。
为什么NHibernate试图将我的实体投射到IDictionary?而且,更重要的是:我怎样才能做到这一点?我错过了什么?
答案 0 :(得分:1)
我在这里可以看到三个问题。首先,您使用了与以下内容相关的映射:
引用:
以下示例演示了使用地图(字典)的表示。首先,在映射文件中,必须声明实体名称而不是(或除了)类名称之外:
<hibernate-mapping>
<class entity-name="Customer">
...
我们可以在 entity-name
上方的映射中看到这一点,而不是 name
。如示例所示,如果我们使用动态,那么我们将继续:
// Create a customer
var frank = new Dictionary<string, object>();
frank["name"] = "Frank";
...
// Save customer
s.Save("Customer", frank);
请参阅:
引用:
<class
name="ClassName" (1)
...
(1)name:持久化类(或接口)的完全限定的.NET类名,包括其程序集名称。
因此,我们不能使用动态映射,而是使用标准类映射:
// Instead of this
// <class entity-name="UserManager.Model.Role" table="roles">
// we should use this
<class name="UserManager.Model.Role" table="roles">
其次,枚举应该映射到 int
列,并使用此元素映射(我也使用permissionId
作为列名来表明它应该是int ):
<element column="permissionId" type="UserManager.Model.Permission"/>
总结这应该是工作映射:
<class name="UserManager.Model.Role" table="roles">
<id name="Id" type="int">
<generator class="identity" />
</id>
<property name="Name" column="name" type="string"/>
<set name="Permissions" table="permissions">
<key column="role"/>
//<!--<element column="name" type="string"/>-->
<element column="permissionId" type="UserManager.Model.Permission"/>
</set>
</class>
第三个问题可能是交换iesi
和System
ISet
。它应该是这样的:
using Iesi.Collections.Generic;
public class Role
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual ISet<Permission> Permissions { get; set; }
public Role()
{
//Permissions = new HashSet<Permission>();
Permissions = new HashedSet<Permission>();
}
}