【问题标题】:Nhibernate: Trouble mapping a one-to-many relationshipNhibernate:映射一对多关系的麻烦
【发布时间】:2026-02-10 11:20:03
【问题描述】:

我对 nhibernate 非常非常陌生,我敢肯定我在这里忽略了很多明显的事情,但是我已经寻找了几天的答案,根本找不到适合我的具体问题的解决方案。我真的非常感谢您的帮助。

我先描述一下我的问题,然后贴出代码:

在我的对象模型中,我有一个 IList 为“Organizer”的“Event”。我想使用 nhibernate,以便在执行“session.Save(anEvent)”时,将数据写入数据库中的三个表:Events、Organizers 和 Organizers_Events(连接表)。当我使用以下代码时,出现以下错误:

Invalid column name 'EventID'

我的代码: 首先,.hbm 文件:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="BLL"
                   namespace="BusinessLogic">

  <class name="Event" table="Events">
    <id name="EventID">
      <column name="ID"/>
      <generator class="native" />
    </id>
    <property name="Name">
      <column name="Name"/>
    </property>
    <bag name="Organizers" table="Organizers_Events" inverse="false" cascade="all-delete-orphan" lazy="true" access="nosetter.camelcase-underscore" >
      <key column="EventID"/>
      <one-to-many class="Organizer" />
    </bag>
  </class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="BLL"
                   namespace="BusinessLogic">

  <class name="Organizer" table="Organizers">
    <id name="Id">
      <column name="ID"/>
      <generator class="native" />
    </id>
    <property name="FullName">
      <column name="FullName"/>
    </property>
    <many-to-one name="TheEvent" column="EventID" />
  </class>
</hibernate-mapping>

接下来,对象:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

/// <summary>
/// Summary description for Event
/// </summary>
/// 

namespace BusinessLogic
{
    public class Event
    {
        private int eventID;

        public virtual int EventID
        {
            get { return eventID; }
            set { eventID = value; }
        }
        private IList<Organizer> _organizers = null;

        public virtual IList<Organizer> Organizers
        {
            get { return _organizers; }
            set { _organizers = value; }
        }
        public Event()
        {
            //
            // TODO: Add constructor logic here
            //
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BusinessLogic
{
    public class Organizer:Invitee
    {
        private Event theEvent = new Event();

        public virtual Event TheEvent
        {
            get { return theEvent; }
            set { theEvent = value; }
        }
    }
}

最后是数据库架构:

CREATE TABLE [dbo].[Events](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](max) NOT NULL
) ON [PRIMARY]

CREATE TABLE [dbo].[Organizers](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [FullName] [nvarchar](550) NULL
) ON [PRIMARY]

CREATE TABLE [dbo].[Organizers_Events](
    [OrganizerID] [int] NOT NULL,
    [EventID] [int] NOT NULL
) ON [PRIMARY]

我已经删除了不相关的数据以简化问题。我不认为其他任何东西对我的问题有任何影响。出于我们的目的,我只希望 Event 对象将其 EventID 和 Name 写入 Events 表,IList 中的每个组织者对象将其 ID 和 FullName 写入 Organizers 表,并将 EventID 和 Organizer 的 ID 写入Organizers_Events 表。

我做错了什么?如果很多,请告诉我。或者,如果网上已有我错过的答案,请指导我。

【问题讨论】:

  • Event 和 Organizer 之间的关系真的是一对多(多对一)的关系吗?组织者可以举办多个活动吗?一个活动可以有多个组织者吗?
  • 我决定架构允许一个活动有多个组织者,但只有一个创建者。

标签: c# asp.net .net nhibernate nhibernate-mapping


【解决方案1】:

在一对多关联中,您不需要连接表。只有在多对多关联中才需要连接表。正确映射

<bag name="Organizers" inverse="false" cascade="all-delete-orphan" lazy="true" access="nosetter.camelcase-underscore" >
    <key column="EventID"/>
    <one-to-many class="Organizer" />
</bag>

为一对多关联正确的数据库架构

CREATE TABLE [dbo].[Events]
(
  [ID] [int] IDENTITY(1,1) NOT NULL,
  [Name] [nvarchar](max) NOT NULL
)
 ON [PRIMARY] 

CREATE TABLE [dbo].[Organizers]
( 
 [ID] [int] IDENTITY(1,1) NOT NULL, 
 [FullName] [nvarchar](550) NULL,
 [EventID] [int] NOT NULL // add FK constraint here
) 
ON [PRIMARY]   

【讨论】:

  • 感谢您的回复。那肯定做了一些事情,但现在我收到了这个错误:“对象引用了一个未保存的瞬态实例 - 在刷新之前保存瞬态实例或将属性的级联操作设置为使其自动保存的东西。”这是一个与以前不同的错误,但我不确定它是否与我映射它的方式有关。
  • 好的,我发现了第二个错误。我需要添加:,以下属性:cascade="all"。谢谢您的帮助!我无法投票,因为我没有 15 点声望点,但是谢谢!
【解决方案2】:

我想你忘了把 inverse="false" 放在你的包声明中:

<bag name="Organizers" inverse="false" table="Organizers_Events" cascade="all-delete-orphan" lazy="true" access="nosetter.camelcase-underscore" >

【讨论】:

  • 我刚刚编辑了代码以使用“inverse='false'”,它仍然不起作用