我希望能够在我的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);
}
}
答案 0 :(得分:1)
我不确定真正的问题是什么:
...但是这会导致为每个实体加载所有Notes,我只想加载该特定实体的注释...
延迟加载是否存在问题?或者实际上Entity1和Entity2可以具有相同的ID,因此引用是混合的? (我希望这应该是以下答案的一部分)
无论如何,我会说我们可以实现您的需求:只用一个表 EntityToNotes 映射Note
。这很好。
但是,一般来说,我会鼓励你使用many-to-many
。这只是我自己的感受,体验。以下是一些更多解释的链接:
解决方案草案:
所以,首先我们必须用两列扩展表“EntityToNotes”
EntityToNoteId
列 - 我们需要新配对对象的主键Discriminator
专栏Discriminator列将用于(几乎像标准继承)
Discriminator
值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
的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
获得了很多