Почему NHibernate сообщает, что мой фильтр не настроен?

#nhibernate #nhibernate-configuration

#nhibernate #nhibernate-конфигурация

Вопрос:

Я пытаюсь использовать глобальный фильтр в NHibernate, и, насколько я могу судить, я делаю именно то, что делают все учебные пособия, но я получаю исключение.

Мой .hbm.xml файл содержит следующее:

 ...
<class name="NHibernateSandbox.Foo, NHibernateSandbox" table="Foo">
    ...
    <property column="Content" type="String" name="Content" not-null="true" length="100" />
    <property column="Deleted" type="Boolean" name="Deleted" not-null="true" />
    <filter name="Foo_Nondeleted" condition="Deleted = false" />
</class>
  

Тогда у меня есть простой тестовый класс:

 Configuration cfg = new Configuration();
cfg.Configure();

using (ISessionFactory sf = cfg.BuildSessionFactory()) {
    using (ISession session = sf.OpenSession()) {
        session.EnableFilter("Foo_Nondeleted");
        IQuery query = session.CreateQuery("FROM NHibernateSandbox.Foo");
        foreach (Foo foo in query.List<Foo>()) {
            Console.WriteLine(foo.Content);
        }
    }
}
  

Если я удаляю EnableFilter строку, она работает как ожидалось: печатаются как удаленные, так и восстановленные строки. Однако со EnableFilter строкой я получаю исключение NHibernateException

 No such filter configured [Foo_Nondeleted]
  at NHibernate.Impl.SessionFactoryImpl.GetFilterDefinition(String filterName)
  at NHibernate.Impl.SessionImpl.EnableFilter(String filterName)
  at NHibernateSandbox.Program.Main(String[] args)
  

Если я настрою log4net как подробный, то я увижу

 INFO  NHibernate.Cfg.HbmBinder - Mapping class: NHibernateSandbox.Foo -> Foo
DEBUG NHibernate.Cfg.HbmBinder - Mapped property: Id -> RID, type: Int32
DEBUG NHibernate.Cfg.HbmBinder - Mapped property: Content -> Content, type: String
DEBUG NHibernate.Cfg.HbmBinder - Mapped property: Deleted -> Deleted, type: Boolean
DEBUG NHibernate.Cfg.HbmBinder - Applying filter [Foo_Nondeleted] as [Deleted = false]
  

Какой недостающий шаг между «применением фильтра» и фильтром, который «настроен» и доступен для сеанса?

Ответ №1:

Недостаточно добавить фильтр в класс: вы также должны его определить. Это сводится к добавлению

 <filter-def name="Foo_Nondeleted"></filter-def>
  

к .hbm.xml досье. Обратите внимание, что здесь есть подвох: хотя учебные пособия показывают его перед классами, он должен быть помещен после них в XML, иначе вы получите XmlSchemaValidationException .

Необходимо внести еще одно небольшое изменение: даже если вы, возможно query.substitutions , настроили сопоставление false с 0 , оно не применяется к условию фильтра, поэтому вам придется изменить фильтр на

 <filter name="Foo_Nondeleted" condition="Deleted = 0" />