如何映射通过只读属性访问的集合?

时间:2011-01-31 15:27:59

标签: fluent-nhibernate

如何使用约定映射零件集合?

public class Part
{
  public virtual int Id { get; set; }
  public virtual string Name { get; set; }
}

public class Car
{
  private readonly List<Part> _parts = new List<Part>();

  public virtual int Id { get; set; }

  public virtual IList<Part> Parts
  {
    get { return _parts.AsReadOnly(); }
  }
}

我已经尝试过这个约定,但它总是希望字段名称没有下划线前缀:

public class HasManyConvention : IHasManyConvention
{
  public void Apply(IOneToManyCollectionInstance instance)
  {
    instance.Access.ReadOnlyPropertyThroughCamelCaseField(CamelCasePrefix.Underscore);
  }
}

我已经尝试使用1.2.0.694和2.0.0.698版本,结果相同:

"Could not find field 'parts' in class 'TestFluentNHibernate.Car'"

2 个答案:

答案 0 :(得分:0)

希望这会有所帮助。尝试...

public class Car
{
  protected virtual List<Part> _parts { get;set; }

  public Car()
  {
    // Initialize "Parts" to not be null
    this.Parts = new List<Part>();
  }
  public void PopulateParts (int someID)
  {
    // Do a call out to one of your helpers to populate "Parts"
    // so it can be used.
    //this.Parts = SomeCall(someID);
  }

  public virtual int Id { get; set; }

  public virtual IList<Part> Parts
  {
    get { return this._parts; } // No need for "ReadOnly" since "protected set" will prevent changes outside of this class.
    protected set { this._parts = value; }
  }
}

受保护的集合将使其成为Car类之外的只读元素。 由于我没有看到你将如何填充零件,我创建了一个名为“PopulateParts”的调用作为一个钩子,因此你可以填充List。

答案 1 :(得分:0)

首先,您的_parts成员不能是只读的。 NHibernate需要对成员的写访问权来设置值/引用。要通过Parts属性返回真正的只读集合,您必须返回System.Collections.ObjectModel.ReadOnlyCollection。如果你只返回f.ex,这也“删除”仍然存在的读/写集合类型中的所有方法。 list.AsReadOnly()。以这种方式返回的只读列表仍然具有.Add()方法和其他编辑集合的方法,但它们将导致运行时异常,因此返回ReadOnlyCollection开始是一个很好的防止这种可能性。

很多人似乎都喜欢返回IEnumerable,它也是只读的,但它可以转换为List或其他读/写集合类型并以这种方式改变。

您必须实现AddPart和RemovePart方法,以允许外部代码向只读集合添加和删除项目。

您的约定看起来是正确的,我使用与1.2.0.694完全相同的语法,我的约定:

     instance.Key.Column(instance.EntityType.Name + "Fk");
     instance.Fetch.Subselect();
     instance.Inverse();
     instance.Cascade.All();
     instance.Access.ReadOnlyPropertyThroughCamelCaseField(CamelCasePrefix.Underscore);

示例类:

public class Car
{
    private List<Part> _parts;

    public Car()
    {
        // Initialize member collection _parts
        _parts = new List<Part>();
    }

    public virtual int Id { get; set; }

    // Return readonlycollection here, ReadOnlyCollection implements 
    // IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable,
    // so the returned list can be any collection type inheriting from these base types.
    public ReadOnlyCollection<Part> Parts
    {
        get { return new List<Part>(_parts).AsReadOnly(); } }
    }

    public AddPart(Part part)
    {
        // Usually I don't want duplicates
        if (!_parts.Contains(part))
            _parts.Add(part);
    }
}