加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 如何在NHibernate中映射多对多对多的三元关系?

发布时间:2020-12-15 22:24:26 所属栏目:百科 来源:网络整理
导读:试图进行多对多关联. 到目前为止我所拥有的是: namespace com.example // Assembly = com.example{ public class Foo { public virtual long Id { get; set; } public virtual IDictionarystring,ISetPersistentClass MappedCollections { get; set; } } pu
试图进行多对多关联.

到目前为止我所拥有的是:

namespace com.example // Assembly = com.example
{

    public class Foo
    {
        public virtual long Id { get; set; }
        public virtual IDictionary<string,ISet<PersistentClass>> MappedCollections { get; set; }
    }

    public class PersistentClass
    {
        public virtual long Id { get; protected set; }
        public virtual string Prop { get; set; }
    }
}

这是我的映射:

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

  <class name="com.example.Foo,com.example">
    <id name="Id" type="Int64" generator="hilo" />
    <map name="MappedCollections">
      <key column="Id" />
      <index column="Key" type="String" />
      <many-to-many class="com.example.PersistentClass,com.example" />
    </map>
  </class>

  <class name="com.example.PersistentClass,com.example">
    <id name="Id" type="Int64" generator="hilo" />
    <property name="Prop" />
  </class>

</hibernate-mapping>

创建模式会生成以下SQL(SqlServer示例):

if exists (select 1 from sys.objects where object_id = OBJECT_ID(N'[FKC8D94E45A4783B9]') AND parent_object_id = OBJECT_ID('MappedCollections'))
alter table MappedCollections  drop constraint FKC8D94E45A4783B9


if exists (select 1 from sys.objects where object_id = OBJECT_ID(N'[FKC8D94E46534DBE0]') AND parent_object_id = OBJECT_ID('MappedCollections'))
alter table MappedCollections  drop constraint FKC8D94E46534DBE0


if exists (select * from dbo.sysobjects where id = object_id(N'Foo') and OBJECTPROPERTY(id,N'IsUserTable') = 1) drop table Foo

if exists (select * from dbo.sysobjects where id = object_id(N'MappedCollections') and OBJECTPROPERTY(id,N'IsUserTable') = 1) drop table MappedCollections

if exists (select * from dbo.sysobjects where id = object_id(N'PersistentClass') and OBJECTPROPERTY(id,N'IsUserTable') = 1) drop table PersistentClass

if exists (select * from dbo.sysobjects where id = object_id(N'hibernate_unique_key') and OBJECTPROPERTY(id,N'IsUserTable') = 1) drop table hibernate_unique_key

create table Foo (
    Id BIGINT not null,primary key (Id)
)

create table MappedCollections (
    Id BIGINT not null,elt BIGINT not null,Key NVARCHAR(255) not null,primary key (Id,Key) -- !! WRONG !! should be unique (Id,elt,Key)
)

create table PersistentClass (
    Id BIGINT not null,Prop NVARCHAR(255) null,primary key (Id)
)

alter table MappedCollections 
    add constraint FKC8D94E45A4783B9 
    foreign key (elt) 
    references PersistentClass

alter table MappedCollections 
    add constraint FKC8D94E46534DBE0 
    foreign key (Id) 
    references Foo

create table hibernate_unique_key (
     next_hi BIGINT 
)

insert into hibernate_unique_key values ( 1 )

知道我做错了什么吗?从我们的SQL中,我们可以看到它持久化为IDictionary< string,PersistentClass>而不是IDictionary< string,ISet< PersistentClass>,我不希望许多Foo与多对字符串和Persistent类的多对多关系,其中该对对于每个Foo是唯一的.所有三个值都应创建唯一值.

我怎样才能做到这一点?

(注意:我包含了Hibernate标签,因为无论是Hibernate还是NHibernate,这种关系的xml映射应该是相同的)

解决方法

虽然它创建了一个不必要的连接,但是创建另一个实体可以做到这一点,同时保持一个非常相似

基本上:

namespace com.example // Assembly = com.example
{

    public class Foo
    {
        public virtual long Id { get; set; }

        public virtual ReadOnlyDictionary<string,ISet<PersistentClass>> MappedCollections 
        { 
            get 
            { 
                return new ReadOnlyDictionary<string,ISet<PersistentClass>>(_mc); 
            } 
        }

        protected virtual IDictionary<string,PersistentClassSet> _mc { get; set; }
        public virtual void InitializeCollection(string key)
        {
            if (!_mk.ContainsKey(key))
                _mc[key] = new PersistentClassSet();
        }
    }

    public class PersistentClass
    {
        public virtual long Id { get; protected set; }
        public virtual string Prop { get; set; }
    }

    internal class PersistentClassSet : ISet<PersisitentClass>
    {
        public PersistentClassSet()
        {
            Proxy = new HashSet<PersistentClass>();
        }

        protected virtual long Id { get; set; }
        protected virtual ISet<PersistentClass> Proxy { get; set; }

        public bool Add(PersistentClass item)
        {
            return Proxy.Add(item);
        }

        // other ISet implementations delegated to Proxy 
    }
}

映射如下:

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

  <class name="com.example.Foo,com.example">
    <id name="Id" type="Int64" generator="hilo" />
    <map name="MappedCollections">
      <key column="Id" />
      <index column="Key" type="String" />
      <many-to-many class="com.example.PersistentClassSet,com.example">
    <id name="Id" type="Int64" generator="hilo" />
    <property name="Prop" />
  </class>

  <class name="com.example.PersistentClassSet,com.example">
    <id name="Id" type="Int64" generator="hilo" />
    <set name="Proxy">
      <key column="Id"/>
      <many-to-many class="com.example.PersistentClass,com.example" />
    </set>
  </class>
</hibernate-mapping>

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读