我试图弄清楚这个问题很长一段时间。我有一个 hacky 的方法来让它工作。
我只想知道这在 Fluent NHibernate 映射中是否可行。
假设我有两个表,例如:
Table ComissionLevel
{
Year,
ComissionLevelID,
... other properties ....
}
primary key (Year,ComissionLevelID)
Table ClientCommission
{
Year,
ClientID,
CommissionLevelID_1,
CommissionLevelID_2,
... other properties ...
}
primary key (Year,ClientID)
foreign key CommissionLevel1 (Year,CommissionLevelID_1)
foreign key CommissionLevel2 (Year,CommissionLevelID_2)
目前我的映射如下:
public ComissionLevelMap()
{
Schema("XXXX");
Table("ComissionLevel");
LazyLoad();
CompositeId()
.KeyProperty(x => x.Year, set => {
set.ColumnName("Year");
set.Access.Property(); } )
.KeyProperty(x => x.CommissionLevelID, set => {
set.ColumnName("CommissionLevelID");
set.Length(10);
set.Access.Property(); } );
HasMany<ClientCommission>(x => x.ClientCommissions)
.Access.Property()
.AsSet()
.Cascade.AllDeleteOrphan()
.LazyLoad()
.Inverse()
.Generic()
.KeyColumns.Add("Year", mapping => mapping.Name("Year")
.SqlType("NUMBER")
.Nullable())
.KeyColumns.Add("CommissionLevelID_1", mapping => mapping.Name("CommissionLevelID_1")
.SqlType("VARCHAR2")
.Nullable()
.Length(10));
HasMany<ClientCommission>(x => x.ClientCommission2s)
.Access.Property()
.AsSet()
.Cascade.AllDeleteOrphan()
.LazyLoad()
.Inverse()
.Generic()
.KeyColumns.Add("Year", mapping => mapping.Name("Year")
.SqlType("NUMBER")
.Nullable())
.KeyColumns.Add("CommissionLevelID_2", mapping => mapping.Name("CommissionLevelID_2")
.SqlType("VARCHAR2")
.Nullable()
.Length(10));
}
public ClientCommissionMap()
{
Schema("XXXXX");
Table("ClientCommission");
LazyLoad();
CompositeId()
.KeyProperty(x => x.ClientID, set => {
set.ColumnName("ClientID");
set.Length(10);
set.Access.Property(); } )
.KeyProperty(x => x.Year, set => {
set.ColumnName("Year");
set.Access.Property(); } );
References(x => x.ComissionLevel1)
.Class<ComissionLevel>()
.Access.Property()
.Cascade.None()
.LazyLoad()
.Insert()
.Update()
.Columns("Year", "CommissionLevelID_1");
References(x => x.ComissionLevel2)
.Class<ComissionLevel>()
.Access.Property()
.Cascade.None()
.LazyLoad()
.Insert()
.Update()
.Columns("Year", "CommissionLevelID_2");
}
我现在的问题是每当我创建一个 CommissionLevel 并将 ClientCommission 分配给它的集合时,如果我通过调用 session.save(CommissionLevel) 保存它们,它会抛出一个异常
<Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index>.
我的问题是:
ClientCommission commission = new ClientCommission{Year = 2012, ClientID =SomeGuid};
CommissionLevel newCommissionLevel = new CommissionLevel{Year = 2012, CommissionLevelID =NewCommissionLevelGuid};
newCommissionLevel.ClientCommission1s.Add(commission);
newCommissionLevel.ClientCommission2s.Add(commission);
CommissionLevelRepo.Save(newCommissionLevel);
当我调用 CommissionLevelRepo.Save(newCommissionLevel) 时,NHibernate 是否也会更新 ClientCommission.ComissionLevel1 和 ClientCommission.ComissionLevel2
或者我必须说
ClientCommission.ComissionLevel1 = newCommissionLevel;
ClientCommission.ComissionLevel2 = newCommissionLevel;
有人可以告诉我映射这两个类的正确方法吗?
非常感谢。
最佳答案
简答:您不能为多个引用共享列
长答案: NHibernate 处理每个引用彼此独立,但确实消除了插入语句中的重复列,因此引用尝试访问不再存在的列。这样做是因为如果对象模型中的 to 引用之间的共享列不同,则它无法确定哪个是正确的。
如果您可以更改数据库架构并使 ID 唯一,则在 ID 和引用中一起忽略年份。
更新:
你可以简化一些映射
CompositeId()
.KeyProperty(x => x.Year, set => {
set.ColumnName("Year");
set.Access.Property(); } )
.KeyProperty(x => x.CommissionLevelID, set => {
set.ColumnName("CommissionLevelID");
set.Length(10);
set.Access.Property(); } );
// to
CompositeId()
.KeyProperty(x => x.Year) // columnname is equal propertyname by default
.KeyProperty(x => x.CommissionLevelID, set => set.Length(10).Access.Property()); // property is default access and can also be left out
.SqlType("VARCHAR2").Length(10)
// to
.Length(10) or .SqlType("VARCHAR2")
// because length is ignored when sqltype is specified
关于nhibernate - Fluent Nhibernate 复合键映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11286892/