我正在使用Fluent NHibernate,我试图映射多个属性,只是绕过连接表。棘手的是,连接表有一个列,用于确定它的关系类型。
出于这个问题的目的,让我们说我有个人表和关系表。
PersonTable (PersonId, Name, etc)
RelationTable (RelationType, PersonIdA, PersonIdB)
我想在Person类中为每种类型的关系引入一个集合属性,例如:儿子,女儿等等。
HasManyToMany<Person>(x => x.Sons)
.Table("RelationTable")
.ParentKeyColumn("PersonIdA")
.ChildKeyColumn("PersonIdB")
.Where("RelationType='A_IS_FATHER_OF_B_BOY'");
HasManyToMany<Person>(x => x.Daughters)
.Table("RelationTable")
.ParentKeyColumn("PersonIdA")
.ChildKeyColumn("PersonIdB")
.Where("RelationType='A_IS_FATHER_OF_B_GIRL'");
以上映射用于从数据库读取,但不用于插入,例如:
Person john = PersonDAO.GetByName("John"); // the Sons and Daughters are loaded fine based on mappings above
john.Sons.Add(new Person("Jack")); // let's add a new son
PersonDAO.Save(john); // this fails because RelationType is null
基本上,在将Jack作为John的新儿子保存在RelationTable中时,我需要使用&#34; A_IS_FATHER_OF_B_BOY&#34;填充RelationType,这当前没有发生。 指令.Where(&#34; RelationType =&#39; A_IS_FATHER_OF_B_BOY&#39;&#34;)仅对加载有效,但不能用于保存。
有什么想法吗?我认为这有点类似于子类的Discriminator属性。
任何帮助表示赞赏。感谢。
答案 0 :(得分:1)
我会说,正如你在评论中指出的那样:
实际上我确实将RelationTable映射为2个
many-to-one
对Person的引用(作为PersonA和PersonB)。使用one-to-many
(HasMany),您如何建议我在Person类中映射Sons和Daughters(两个List<Person>
),同时考虑上面的鉴别器值
所以我眼中的配对对象是
public class PersonRelation
{
// the pairing table must contain the key column, surrogated ID
public virtual int Id { get; protected set; } // this is a must.
public virtual Person Parent { get; set; }
public virtual Person Child { get; set; }
public virtual string RelationType { get; set; }
}
这张桌子必须有钥匙。只需向SQL Server注入一些IDENTITY列,但有一些带有代理(业务域无关)密钥。
这是我们的Person实体
public class Person
{
IList<PersonRelation> _sons;
IList<PersonRelation> _daughters;
..,
public virtual IList<PersonRelation> Sons
{
get { return _sons ?? (_sons = new List<PersonRelation>()); }
set { _sons = value; }
}
public virtual IList<PersonRelation> Daughters
{
get { return _daughters?? (_daughters= new List<PersonRelation>()); }
set { _daughters= value; }
}
}
Sons 的映射(Daughters会相同):
HasMany<PersonRelation>(x => x.Sons)
// .Table("RelationTable") // not needed - part of PersonRleation mapping
.KeyColumn("PersonIdA")
.Where("RelationType='A_IS_FATHER_OF_B_BOY'")
.Inverse()
.Cascade.AllDeleteOrphan()
;
如果我们总是保证,那么在添加Son时,我们也可以正确设置RelationType
var parent = ...; // new, loaded
var child = ...; // new, loaded
var relation = new PersonRelation
{
Parent = parent;
Child = child;
RelationType = "A_IS_FATHER_OF_B_BOY";
};
parnet.Sons.Add(relation);
这必须是Businese图层AddSon()的一部分,或者它可能是POCO公共方法......
注意:我们也可以映射该关系的反向结束...即使没有relationType过滤:
public class Person
{
... as above
public virtual IList<PersonRelation> Parents { get; set; }
HasMany<PersonRelation>(x => x.Parents)
// instead of this
// .KeyColumn("PersonIdA")
// we need this column
.KeyColumn("PersonIdB")
;