Вам не нужен тип объекта. Посмотрите на сопоставление любого типа (оно сохраняет имя типа в базе данных в таблице отношений, но оно не требуется в модели сущностей).
См. это сообщение в блоге ayende .
Редактировать: попытался написать пример.
Вы можете иметь собственную таблицу для каждого помеченного объекта, это легко и просто, вам даже не нужны никакие типы:
<class name="Tag">
<!-- ... -->
<property name="Name"/>
</class>
<class name="Image">
<!-- ... -->
<bag name="Tags" table="Image_Tags">
<key column="Image_FK"/>
<many-to-many class="Tag" column="TagId "/>
</bag>
</class>
Пытался использовать некоторые расширенные функции, чтобы отобразить его в одну таблицу, но я думаю, что это не сработает так:
<class name="Tag">
<!-- ... -->
<property name="Name"/>
<bag name="Objects" table="tblTagEntity" access="noop">
<key column="TagId"/>
<many-to-any id-type="System.Int64" meta-type="System.String">
<meta-value
value="IMAGE"
class="Image"/>
<meta-value
value="BLOG"
class="Blog"/>
<column name="EntityType"/>
<column name="EntityId"/>
</many-to-any>
</bag>
</class>
<class name="Image">
<!-- ... -->
<bag name="Tags" table="tblTagEntity" where="EntityType='IMAGE'">
<key column="EntityId"/>
<many-to-many class="Tag" column="TagId "/>
</bag>
</class>
Трюки здесь:
access="noop"
для указания внешнего ключа без свойства в модели объекта, см. Этот пост .
where="EntityType='IMAGE'"
для фильтрации загруженных данных.
Проблема в том, что, скорее всего, для EntityType не установлено какое-либо полезное значение. Это может быть где-то исправлено, но я не думаю, что оно того стоит.
У кого-то еще есть идея получше.
Редактировать 2: другое (рабочее) решение
сделать таблицу ассоциаций сущностью:
короче:
- Tag => TagEntity: не отображается или обратная связь один-ко-многим (noop)
- TagEntity => Tag: многие-к-одному
- TagEntity => Объект: любой
- Object => TagEntity: обратное отношение один ко многим
Это должно работать прямо вперед.
классы:
class Tag
{
string Name { get; set; }
}
class TagEntity
{
Tag Tag { get; set; }
object Entity { get; set; }
}
class Image
{
IList<TagEntity> tags { get; private set; }
}
Единственным недостатком является то, что вы должны убедиться, что двунаправленные ассоциации согласованы без загрузки большого количества данных. Обратите внимание, что обратные коллекции не сохраняются.
Редактировать 2: заметки о производительности
Когда вы добавляете / удаляете теги, вы можете сделать трюк. TagEntity имеет ссылку на помеченный объект. У сущности также есть список TagEntities, но он помечен как обратный. (Это означает, что они загружены, но не сохранены.)
Вы можете добавлять и удалять теги без загрузки сущности и без загрузки всех тегов.
Добавление:
- Получить тег для добавления (или загрузить прокси, если у вас есть идентификатор тега)
- Загрузить Entity (просто прокси, используя session.Load, здесь нет доступа к БД)
- создание нового TagEntity, назначение тега и прокси-объекта лица
- сохранить TagEntity
Удаление:
- Получить TagEntity для удаления
- удалить TagEntity.
В течение сеанса у вас нет этого тега, назначенного / удаленного из TagEntity. Это работает нормально, если вы только добавляете или удаляете теги в этой транзакции.
Если вы определите список TagEntities для Tag, вы можете сделать то же самое, не загружая все TagEntities, просто добавив или удалив один.