通过代码在由多列组成的主键上定义 NHibernate 映射
Define NHibernate mapping by code on primary key consisting of multiple columns
有人知道仅使用 NHibernate 映射在多列上创建引用吗?此映射只允许一列。
Bag(p => p.Childs,
map =>
{
map.Key(k =>
{
k.Column("KeyPart1");
});
map.Key(k =>
{
k.Column("KeyPart2");
});
}
, ce => ce.OneToMany());
这导致映射(剥离 xml 标签):
<bag name="Childs">
<key column="KeyPart1" />
<one-to-many class="Child" />
</bag>
这会导致错误:
结果消息:NHibernate.FKUnmatchingColumnsException:外键 (FK1C5AAEC658BD05ED:Child [KeyPart2])) 必须与引用的主键 (Parent [KeyPart1, KeyPart2])
具有相同的列数
子映射是:
ManyToOne(p => p.Parent,
map => map.Columns(
col1 =>
{
col1.Name("KeyPart1");
},
col2 =>
{
col2.Name("KeyPart2");
}
));
但我想我需要这个映射,包括两个关键部分:
<bag name="Childs">
<key column="KeyPart1" />
<key column="KeyPart2" />
<one-to-many class="Child" />
</bag>
这是 类 的完整结构:
public class ParentIdentifier
{
public virtual string KeyPart1 { get; set; }
public virtual string KeyPart2 { get; set; }
public override bool Equals(object obj)
{
if (obj == null)
return false;
var t = obj as ParentIdentifier;
if (t == null)
return false;
if (KeyPart1 == t.KeyPart1 && KeyPart2 == t.KeyPart2)
return true;
return false;
}
public override int GetHashCode()
{
return (KeyPart1 + "|" + KeyPart2).GetHashCode();
}
public override string ToString()
{
return string.Format("KeyPart1 = {0}; KeyPart2 = {1}", KeyPart1, KeyPart2);
}
}
[Serializable]
public class Parent
{
#region Primary key
public virtual ParentIdentifier Id { get; set; }
#endregion Primary key
public Parent()
{
Childs = new List<Child>();
}
public virtual IList<Child> Childs { get; set; }
}
public class ParentMap : ClassMapping<Parent>
{
public ParentMap()
{
Table("Parent");
ComponentAsId(
x => x.Id,
caim =>
{
caim.Property(x => x.KeyPart1, pm =>
{
pm.Column("KeyPart1");
pm.Length(20);
} );
caim.Property(x => x.KeyPart2, pm =>
{
pm.Column("KeyPart2");
pm.Length(64);
} );
});
Bag(p => p.Childs,
map =>
{
map.Key(k =>
{
k.Column("KeyPart1");
});
map.Key(k =>
{
k.Column("KeyPart2");
});
}
, ce => ce.OneToMany());
}
}
[Serializable]
public class Child
{
#region Primary key
public virtual int ChildId { get; set; }
#endregion Primary key
public virtual Parent Parent { get; set; }
}
public class ChildMap : ClassMapping<Child>
{
public ChildMap()
{
Table("Child");
Id(p => p.ChildId,
map =>
{
map.Generator(Generators.Assigned);
map.Column("ChildId");
});
ManyToOne(p => p.Parent,
map => map.Columns(
col1 =>
{
col1.Name("KeyPart1");
},
col2 =>
{
col2.Name("KeyPart2");
}
));
}
}
因为您调用了 map.Key(...) 两次,所以第二次会覆盖第一次!您应该改为调用:
map.Key(k =>
{
k.Columns(
c1 => c1.Name("c1"),
c2 => c2.Name("c2") /*as many as you want*/
);
});
有人知道仅使用 NHibernate 映射在多列上创建引用吗?此映射只允许一列。
Bag(p => p.Childs,
map =>
{
map.Key(k =>
{
k.Column("KeyPart1");
});
map.Key(k =>
{
k.Column("KeyPart2");
});
}
, ce => ce.OneToMany());
这导致映射(剥离 xml 标签):
<bag name="Childs">
<key column="KeyPart1" />
<one-to-many class="Child" />
</bag>
这会导致错误: 结果消息:NHibernate.FKUnmatchingColumnsException:外键 (FK1C5AAEC658BD05ED:Child [KeyPart2])) 必须与引用的主键 (Parent [KeyPart1, KeyPart2])
具有相同的列数子映射是:
ManyToOne(p => p.Parent,
map => map.Columns(
col1 =>
{
col1.Name("KeyPart1");
},
col2 =>
{
col2.Name("KeyPart2");
}
));
但我想我需要这个映射,包括两个关键部分:
<bag name="Childs">
<key column="KeyPart1" />
<key column="KeyPart2" />
<one-to-many class="Child" />
</bag>
这是 类 的完整结构:
public class ParentIdentifier
{
public virtual string KeyPart1 { get; set; }
public virtual string KeyPart2 { get; set; }
public override bool Equals(object obj)
{
if (obj == null)
return false;
var t = obj as ParentIdentifier;
if (t == null)
return false;
if (KeyPart1 == t.KeyPart1 && KeyPart2 == t.KeyPart2)
return true;
return false;
}
public override int GetHashCode()
{
return (KeyPart1 + "|" + KeyPart2).GetHashCode();
}
public override string ToString()
{
return string.Format("KeyPart1 = {0}; KeyPart2 = {1}", KeyPart1, KeyPart2);
}
}
[Serializable]
public class Parent
{
#region Primary key
public virtual ParentIdentifier Id { get; set; }
#endregion Primary key
public Parent()
{
Childs = new List<Child>();
}
public virtual IList<Child> Childs { get; set; }
}
public class ParentMap : ClassMapping<Parent>
{
public ParentMap()
{
Table("Parent");
ComponentAsId(
x => x.Id,
caim =>
{
caim.Property(x => x.KeyPart1, pm =>
{
pm.Column("KeyPart1");
pm.Length(20);
} );
caim.Property(x => x.KeyPart2, pm =>
{
pm.Column("KeyPart2");
pm.Length(64);
} );
});
Bag(p => p.Childs,
map =>
{
map.Key(k =>
{
k.Column("KeyPart1");
});
map.Key(k =>
{
k.Column("KeyPart2");
});
}
, ce => ce.OneToMany());
}
}
[Serializable]
public class Child
{
#region Primary key
public virtual int ChildId { get; set; }
#endregion Primary key
public virtual Parent Parent { get; set; }
}
public class ChildMap : ClassMapping<Child>
{
public ChildMap()
{
Table("Child");
Id(p => p.ChildId,
map =>
{
map.Generator(Generators.Assigned);
map.Column("ChildId");
});
ManyToOne(p => p.Parent,
map => map.Columns(
col1 =>
{
col1.Name("KeyPart1");
},
col2 =>
{
col2.Name("KeyPart2");
}
));
}
}
因为您调用了 map.Key(...) 两次,所以第二次会覆盖第一次!您应该改为调用:
map.Key(k =>
{
k.Columns(
c1 => c1.Name("c1"),
c2 => c2.Name("c2") /*as many as you want*/
);
});