У меня очень простая настройка:
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 пытается передать мою Entity в IDictionary? И, что еще важнее: как я могу это сделать? Что мне не хватает?
Здесь я вижу три проблемы. Во-первых, вы использовали отображение, относящееся к:
Цитата:
Следующие примеры демонстрируют представление с помощью Maps (Dictionary). Во-первых, в файле сопоставления вместо имени (или в дополнение к) имени класса должно быть объявлено имя объекта:
<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">
Во-вторых, Enum должен быть сопоставлен с столбцом 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>();
}
}