所以,我有一个NHibernate实体,它有一个相关的列表,如下所示:
public class CountSet{
//Some other code here
private readonly IList<int> _instanceCounts;
public virtual IEnumerable<int> InstanceCounts
{
get { return _instanceCounts; }
set
{
_instanceCounts.Clear();
foreach (var instanceCount in value.Distinct())
{
_instanceCounts.Add(instanceCount);
}
}
}
}
我正在使用Fluent NHibernate映射实体,使用自动化,但使用覆盖来映射列表,如下所示:
mapping.HasMany(x => x.InstanceCounts)
.Table(@"CountSetsInstanceCounts")
.KeyColumn(@"InstanceCountSetId")
.Element(@"InstanceCount");
这似乎正确地创建了hbm xml,如下所示:
<bag table="CountSetsInstanceCounts" name="InstanceCounts"
access="field.camelcase-underscore" inverse="true"
cascade="all-delete-orphan">
<key>
<column name="InstanceCountSetId"/>
</key>
<element type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, ">
<column name="InstanceCount"/>
</element>
</bag>
哪个看起来对我不对。但是,当我尝试将这些实体持久保存到数据库时,实体会正确保存,但集合不是。
有关可能发生的事情的任何建议?请随时询问更多信息。
答案 0 :(得分:1)
你快到了。您的映射是正确的,也是C#实体。关键是, int 无法通过“反向”设置进行管理,因为它不是实体。必须将其设置为inverse="false"
。
以这种方式调整映射:
mapping.HasMany(x => x.InstanceCounts)
.Table(@"CountSetsInstanceCounts")
.KeyColumn(@"InstanceCountSetId")
.Element(@"InstanceCount")
.Not.Inverse()
;
答案 1 :(得分:0)
这主要是因为您的自定义setter使用了支持字段。 因此,nhibernate没有用于跟踪更改的引用对象。
你有一些选择来解决它
a)删除自定义逻辑,然后使用
public virtual IEnumerable<int> InstanceCounts
{
get;
set;
}
这应该适用于您当前的映射,因为nh可以跟踪auto属性的更改。
b)更改映射以指定访问权限:.Access.CamelCaseField()
要使其正常工作,您还必须将备用字段的名称更改为不以下划线开头。
作为旁注:您将支持字段定义为只读。如果你暴露你的属性的setter,这没有任何意义。
如果您想拥有只读属性,请删除setter并执行一个方法来设置值列表。 或者,如果您不需要只读标志但仍希望拥有支持字段,请将代码更改为
public virtual IEnumerable<int> InstanceCounts
{
get { return instanceCounts; }
set { instanceCounts = value.ToList(); }
}