4

Попытка создания ассоциации «многие-ко-многим-многим».Как сопоставить тройные отношения «многие-ко-многим» в NHibernate?

То, что я до сих пор это:

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 тегов, потому что XML-отображения для этого отношения должны быть такими же ли Hibernate или NHibernate)

ответ

1

Хотя это создает ненужное соединение, создавая ту или иную компанию может сделать это, в то время как держать очень похожий открытый интерфейс.

в основном:

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" /> 
    </map> 
    </class> 

    <class name="com.example.PersistentClass, 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> 
0

Предположим, у вас есть таблица называется продукт {PRODUCTID, имя), и таблица под названием Bundle { bundleid, name}. Теперь Product и bundle могут иметь много-много картирование. Поэтому создайте новую таблицу под названием BundleProduct {BundleId, ProductId}. Теперь отображение Nhibernate выглядит

ценам ниже
ProductMap 
{ 
    HasManyToMany(x => x.Bundles).Table("BundleProduct").ParentKeyColumn("ProductId").ChildKeyColumn("BundleId").Cascade.None().Inverse().Not.LazyLoad(); 
} 
BundleMap 
{ 
    HasManyToMany(x => x.Products) 
       .Table("BundleProduct") 
       .ParentKeyColumn("BundleId") 
       .ChildKeyColumn("ProductId") 
       .Cascade.All(); 
} 
Смежные вопросы