我希望能够将Notes集合添加到我的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);
}
}
我不确定真正的问题是什么:
然而,这将导致为每个实体加载所有Notes,我只想加载该特定实体的Notes。。。
问题是懒惰加载吗?或者实际上Entity1和Entity2可以具有相同的ID,因此引用是混合的(我预计这应该是下面答案的一部分)
无论如何,我想说,我们可以实现您所需要的:只使用一个表映射Note
EntityToNotes。这很好。
但是,总的来说,我建议您不要使用many-to-many
。这只是我自己的感受和经验。以下是一些有更多解释的链接:
- 在使用流利的nhibernate时,我是否做了很多对很多错误的操作
- NHibernate如何将对照表映射到包
- Nhibernate:如何用一对多关系表示多对多关系
解决方案草案:
因此,首先我们必须用两列扩展表"EntityToNotes"
EntityToNoteId
列-我们需要新配对对象的主键Discriminator
列
鉴别器列将用于(几乎像标准继承)
- 在创建期间插入
Discriminator
值 - 每个实体筛选te
IList<Notes>
这些可能是配对实体(具有收集常见内容的抽象基础)
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
、EntityType2ToNote
的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
…),并且我们能够使用强大的子查询搜索-请参阅查询HasMany参考
此外,事实上,配对可以通过真正的继承映射但这里的要点是:我们引入了配对对象而不是many-to-many
,并获得了很多