Reputation: 17831
I have a very simple setup:
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]
}
And according mapping files:
<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>
But, when I try to create a role and save it:
[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();
}
I get an exception:
System.InvalidCastException: Unable to cast object of type 'UserManager.Model.Role' to type 'System.Collections.IDictionary'.
Why does NHibernate try to cast my Entity to an IDictionary? And, more importantly: How can I make this work? What am I missing?
Upvotes: 1
Views: 209
Reputation: 123891
I can see three problems here. Firstly you've used the mapping related to:
A cite:
The following examples demonstrates the representation using Maps (Dictionary). First, in the mapping file, an entity-name has to be declared instead of (or in addition to) a class name:
<hibernate-mapping>
<class entity-name="Customer">
...
And this is what we can see in the mapping above entity-name
instead of name
. As the example shows if we use dynamic then we would continue:
// Create a customer
var frank = new Dictionary<string, object>();
frank["name"] = "Frank";
...
// Save customer
s.Save("Customer", frank);
See:
A cite:
<class
name="ClassName" (1)
...
(1) name: The fully qualified .NET class name of the persistent class (or interface), including its assembly name.
So, we cannot use dynamic mapping but the standard class mapping:
// Instead of this
// <class entity-name="UserManager.Model.Role" table="roles">
// we should use this
<class name="UserManager.Model.Role" table="roles">
Secondly, the Enum should be mapped to int
column with this element mapping (also I used permissionId
as column name to show that it should be int):
<element column="permissionId" type="UserManager.Model.Permission"/>
Summary this should be working mapping:
<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>
The third issue, could be swapping of iesi
and System
ISet
. It should be like this:
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>();
}
}
Upvotes: 1