NHibernate复合元素多对多

时间:2010-04-04 15:01:46

标签: c# .net nhibernate

我遇到了以下问题。在我的应用程序中,使用实体OwnerArea绑定尽可能多的。

public class Area : DomainObject<int> {        
    private ISet<OwnersPeriod> _owners = new HashedSet<OwnersPeriod>();

    public ICollection<OwnersPeriod> Owners {
        get { return _owners; }
        set {
            Check.Require(value != null);
            _owners = new HashedSet<OwnersPeriod>(value);
        }
    }
}

表Owner2Area具有以下字段:

CREATE TABLE [dbo].[Owner2Area](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [IDOwner] [int] NOT NULL,
    [IDArea] [int] NOT NULL,
    [FirstDate] [datetime] NOT NULL,
    [LastDate] [datetime] NULL,
 CONSTRAINT [PK_Owner2Area] PRIMARY KEY CLUSTERED)

因此对应于OwnersPeriod类

    public class OwnersPeriod {
        private Owner _member;
        private Area _area;    
        public Owner Owner { get {...} set{...} }    
        public Area Area { get { ... } set { ... } }    
        public  DateTime FirstDate { get; set; }    
        public  DateTime? LastDate { get; set; }       
    }

我写了映射

<class lazy="false" name="Core.Domain.Area, Core" table="Areas">
   ...
   <set name="Owners" table="Owner2Area" inverse="true" lazy="true" >
      <key column="IDArea"/>
      <composite-element class="Core.Domain.OwnersPeriod, Core" >
        <parent name="Area" />
        <property name="FirstDate" type="datetime"/>
        <property name="LastDate" type="datetime"/>
        <many-to-one name="Owner" class="Core.Domain.Owner, Core" column="IDOwner"/>
      </composite-element>
    </set>
</class>

对于每个区域,现有数据已成功加载到Owners,但当我在Owner2AreaCreateSQLQuery中添加新记录时,这些数据不会更新为区域。如果我重新打开表单并获得所有区域,则添加链接已成功加载到集合中 如何强制加载,从而记录多对多的关系?
Nhibernate v.2.0.1,db MSSQL 2005

1 个答案:

答案 0 :(得分:0)

如果你使用CreateSQLQuery NHibernate不知道你做了什么。试想一下。添加了CreateSQLQuery,因为使用HQL和CriteriaQuery并不是所有事情都可以。因此,使用CreateSQLQuery,您可以做“特殊事情”。

不建议使用多对多,因为您没有“中间表”的“直接处理”。如果你将实体添加到多对多关系nhibernate方式(修改集合)然后对实体进行更新,你会看到nhibernate从'中间表'中删除所有数据然后插入它再次。所以不好。这就是为什么你可能认为你使用CreateSQLQuery做一个解决方法。 我建议你用3个实体做经典的亲子关系,这样你就可以直接操作'中间表'了。

另一个解决方案是当你更新'中间表'时,你做了一个Evict(这是一个ISession的方法和ISessionFactory中的方法,请查看手册),这个实体受到CreateSQLQuery的影响。但是使用它会强制另一个数据库命中(将加载一个新版本)。 使用父子方法不会对数据库造成影响。