许多实体到一个联结表 NHibernate 建模

Posted

技术标签:

【中文标题】许多实体到一个联结表 NHibernate 建模【英文标题】:Many entities to one junction table NHibernate modelling 【发布时间】:2014-04-24 06:06:11 【问题描述】:

我希望能够在我的 NHibernate 应用程序中的任何主要实体中添加一组 Notes。我可以看到您如何使用每个实体的单独连接表来做到这一点。但是,我希望能够避免这种情况,并且只有一个连接表 - 如果可能的话。

下面是到目前为止的代码,但是这将导致为每个实体加载所有注释,我只想为该特定实体加载注释。我需要采取哪些替代方法?

    public class Entity
    
        public virtual int Id  get; set; 
    

    public class EntityType1 : Entity
    
        public EntityType1()
        
            Notes = new List<Note>();
        
        public virtual string EntityTypeName  get; set; 
        public virtual IList<Note> Notes get;set;
    

    public class EntityType2 : Entity
    
        public EntityType2()
        
            Notes = new List<Note>();
        
        public virtual string EntityType2Name  get; set; 
        public virtual IList<Note> Notes  get; set; 
    

    public class Note
    
        public virtual int Id  get; set; 
        public virtual IList<Entity> Entities  get; set; 
        public virtual string NoteText  get; set; 
    


namespace FluentNHib.Mappings

    public class EntityMap : ClassMap<Entity>
    
        public EntityMap()
        
            Id(m => m.Id);
        
    
    public class EntityType1Map : ClassMap<EntityType1>
    
        public EntityType1Map()
        
            Id(m => m.Id);
            Map(m => m.EntityTypeName1);
            HasManyToMany(m => m.Notes).Table("EntityToNotes")
            .ParentKeyColumn("EntityId")
            .ChildKeyColumn("NoteId")
            .LazyLoad()
            .Cascade.SaveUpdate();
        
    

    public class EntityType2Map : ClassMap<EntityType2>
    
        public EntityType2Map()
        
            Id(m => m.Id);
            Map(m => m.EntityType2ame);
            HasManyToMany(m => m.Notes).Table("EntityToNotes")
            .ParentKeyColumn("EntityId")
            .ChildKeyColumn("NoteId")
            .LazyLoad()
            .Cascade.SaveUpdate();

        
    

    public class NoteMap : ClassMap<Note>
    
        public NoteMap()
        
            Id(m => m.Id);
            Map(m => m.NoteText);
        
    

【问题讨论】:

【参考方案1】:

我不确定真正的问题是什么:

...但是这将导致为每个实体加载所有注释,我只想为该特定实体加载注释...

是延迟加载的问题吗?或者实际上 Entity1 和 Entity2 可以具有相同的 ID,因此引用是混合的? (我希望这应该是下面答案的一部分)

无论如何,我想说我们可以实现您所需要的:将Note 映射到一张表EntityToNotes。这很好。

但是,总的来说,我不鼓励您使用many-to-many。这只是我自己的感觉,经验。下面是一些有更多解释的链接:

Am I doing many to many incorrectly when using fluent nhibernate? NHibernate how do you map a cros-s-reference table to a bag? Nhibernate: How to represent Many-To-Many relationships with One-to-Many relationships?

解决方案草案:

所以,首先我们必须将表 "EntityToNotes" 扩展为两列

EntityToNoteId 列 - 我们需要新配对对象的主键 Discriminator专栏

鉴别器列将用于(几乎像标准继承)

    在创建过程中插入 Discriminator 值 过滤每个实体IList&lt;Notes&gt;

这些可能是配对实体(有一个抽象的基础收集常见的东西)

public abstract class EntityToNote<TEntity>

    public abstract string Discriminator  get; set; 

    public virtual TEntity Entity get;set;
    public virtual Note    Note   get;set;

// the pairing objects
public class EntityType1ToNote : EntityToNote<EntityType1>

    string _discriminator = "EntityType1"; // here we set the discriminator
    public virtual string Discriminator
    
        get  return _discriminator; 
        set  _discriminator = value; 
    
...
// Similar for other pairing objects

实体现在将引用配对对象列表

public class EntityType1 : Entity

    public virtual IList<EntityType1ToNote> Notes get;set;
    ...

public class EntityType2 : Entity

    public virtual IList<EntityType2ToNote> Notes  get; set; 
    ...

这是映射的 sn-p(所有其他实体将具有通常的映射,包括 EntityType1ToNoteEntityType2ToNote...的 ClassMaps)

public class EntityType1Map : ClassMap<EntityType1>

    public EntityType1Map()
    
        Id(m => m.Id);
        Map(m => m.EntityTypeName1);
        HasMany(m => m.Notes)
          // this "table" setting is redundant, it will come from EntityType1ToNote
          //.Table("EntityToNotes")
          .KeyColumn("EntityId")
          // here is the trick, that only related rows will be selected
          .Where("Discriminator = 'EntityType1'")
          .Cascade.AllDeleteOrphan();
    

正如我试图在提供的链接中解释的那样,我们通过这种方式获得了很多。主要是能够在配对表上使用更多列 - 例如Discriminator (以后我们可以有更多的列,例如 SortBy...) 我们可以使用强大的子查询搜索 - 请参阅 Query on HasMany reference

另外,事实上,配对可以通过真正的继承来映射...... 但这里的重点是:我们引入了配对对象,而不是many-to-many,并获得了一个很多

【讨论】:

以上是关于许多实体到一个联结表 NHibernate 建模的主要内容,如果未能解决你的问题,请参考以下文章

实体关系图中的sql联结表如何显示

实体框架与 NHibernate - 性能

在关系数据库中对相同实体之间的多个多对多关系进行建模

如何在实体关系图中表示联结表?

SQL n:n - 联结表中查询的最佳实践

您如何在流利的 nhibernate 中映射和使用连接表?