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

时间:2014-04-24 06:06:12

标签: c# .net nhibernate fluent-nhibernate

我希望能够在我的NHibernate应用程序中为我的任何主要实体添加一组Notes。我可以看到你如何使用每个实体的单独联结表来完成此操作。但是,我希望能够避免这种情况并且只有一个联结表 - 如果可能的话。

以下是目前为止的代码,但是这将导致为每个实体加载所有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 个答案:

答案 0 :(得分:1)

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

  

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

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

无论如何,我会说我们可以实现您的需求:只用一个表 EntityToNotes 映射Note。这很好。

但是,一般来说,我会鼓励你使用many-to-many。这只是我自己的感受,体验。以下是一些更多解释的链接:

解决方案草案:

所以,首先我们必须用两列扩展表“EntityToNotes”

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

Discriminator列将用于(几乎像标准继承)

  1. 在创建期间插入Discriminator
  2. 按实体过滤te IList<Notes>
  3. 这些可能是配对实体(带有收集常见内容的抽象基础)

    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; }
        ...
    

    以下是映射的摘录(所有其他实体都有通常的映射,包括EntityType1ToNote的ClassMaps,EntityType2ToNote ...)

    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获得了很多