NHibernate 映射错误([EntityName] 未映射)

NHibernate mapping error ([EntityName] not mapped)

我的项目(c#、nhibernate、npgsql、nlog)有一个名为 Entry 的实体,应该映射到名为 test 的数据库 table。 Table 包含一些测试条目。

我的申请代码如下:

public void work()
{
    ISessionFactory sessions = new Configuration().Configure().BuildSessionFactory();
    ISession session = sessions.OpenSession();

    IList<Entry> entries = session.CreateQuery("from Entry").List<Entry>();

    foreach (Entry e in entries)
    {
        logger.Debug("Entry: " + e.id + " with " + e.name);
    }
}

Entry 实体如下所示:

namespace pgsql
{
    class Entry
    {
        public virtual int id { get; set; }
        public virtual string name { get; set; }
    }
}

我的 NHibernate 配置结构如下:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <session-factory>
        <property name="connection.driver_class">NHibernate.Driver.NpgsqlDriver</property>
        <property name="dialect">NHibernate.Dialect.PostgreSQLDialect</property>
        <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
        <property name="default_catalog">test</property>
        <property name="default_schema">test</property>
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
        <property name="hbm2ddl.auto">create</property>
        <property name="connection.connection_string">server=localhost;database=*****;uid=*****;pwd=*****;</property>
    </session-factory>
</hibernate-configuration>

Entry实体配置如下:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping schema="test" xmlns="urn:nhibernate-mapping-2.2">
    <class name="Entry" table="test">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name"/>
    </class>
</hibernate-mapping>

这会引发以下错误:

Entry is not mapped [from Entry]

我已经确定,Visual Studio 正在将所有 hbm.xml 文件复制到输出目录。我错过了什么?

根据您的回答进行编辑:

the solution was to initialize with the Assembly:

ISessionFactory sessions = new Configuration().Configure().AddAssembly(Assembly.GetExecutingAssembly()).BuildSessionFactory();

but i still don't know, why it has to be like that.

我会解释为什么必须那样。

您的实体是在与您的应用程序相同的程序集中定义的。
当您调用 Configuration().Configure().BuildSessionFactory() 时,实际上您所有的 HBM 文件都被忽略了。您需要执行以下任一操作才能将 HBM​​ 文件添加到 Configuration 实例:

  • 对每个单独的 HBM 文件使用 new Configuration().AddFile("MyFile.hbm.xml")
  • 使用 new Configuration().Configure().AddAssembly(YourAssembly()) 告诉 NHibernate 查找 所有 HBM 文件并为您添加所有这些文件。
  • 下面链接的文档中提到的其他方式。

由于您没有执行任何一项操作,因此没有实体配置添加到 Configuration。当您尝试 运行 您的 HQL 查询时,NHibernate 正在寻找 Entry 未定义的实体(添加到 Configuration)。因此是错误。

正如您在回答中提到的,您选择了第二种方式将 HBM​​ 文件添加到 Configuration 并且问题消失了。

Another alternative (probably the best) way is to let NHibernate load all of the mapping files contained in an Assembly:

Configuration cfg = new Configuration()
.AddAssembly( "NHibernate.Auction" );

Then NHibernate will look through the assembly for any resources that end with .hbm.xml. This approach eliminates any hardcoded filenames and ensures the mapping files in the assembly get added.

详情请参考doc


原答案

实体名称也应包括命名空间。

IList<Entry> entries = session.CreateQuery("from pgsql.Entry").List<Entry>();

为了让重构更简单,你也可以改成下面这样:

var queryString = string.Format("from {0}", typeof(Entry));
IList<Entry> entries = session.CreateQuery(queryString).List<Entry>();

请参考14.2节。来自 docs.

的 from 子句

不是你的问题的一部分,但是,调用 BuildSessionFactory 是昂贵的。你不需要重复它。您可以在应用程序启动时调用它并维护 ISessionFactory 的实例以备将来使用。

解决方案是使用程序集进行初始化:

ISessionFactory sessions = new Configuration().Configure().AddAssembly(Assembly.GetExecutingAssembly()).BuildSessionFactory();

但我还是不知道,为什么一定要那样。