将int列表映射到nHibernate实体

时间:2013-12-20 17:50:41

标签: c# asp.net nhibernate fluent-nhibernate

所以,我有一个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>

哪个看起来对我不对。但是,当我尝试将这些实体持久保存到数据库时,实体会正确保存,但集合不是。

有关可能发生的事情的任何建议?请随时询问更多信息。

2 个答案:

答案 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(); }
}