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

Fluent nhibernate 如何映射通过只读属性访问的集合?,fluent-nhibernate,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; } pub

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

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(); }
  }
}
我在1.2.0.694和2.0.0.698版本中进行了尝试,结果相同:

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

希望这能有所帮助。试试看

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; }
  }
}
公车
{
受保护的虚拟列表_parts{get;set;}
公共汽车
{
//将“部件”初始化为不为空
this.Parts=新列表();
}
public void PopulateParts(int-someID)
{
//打电话给你的一个助手来填充“零件”
//所以它可以被使用。
//this.Parts=SomeCall(someID);
}
公共虚拟整数Id{get;set;}
公共虚拟IList部件
{
get{return this.\u parts;}//不需要“ReadOnly”,因为“protected set”将阻止在此类之外的更改。
受保护集{this.\u parts=value;}
}
}
受保护集将使其成为Car类之外的只读元素。
因为我不知道您将如何填充部件,所以我创建了一个调用“PopulateParts”作为钩子,以便您可以填充列表。

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

许多人似乎喜欢返回一个IEnumerable,它也是只读的,但它可以转换为列表或其他读/写集合类型,并以这种方式进行更改

您必须实现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);
    }
}
公车
{
私人清单(零件);;
公共汽车
{
//初始化成员集合\u部件
_零件=新列表();
}
公共虚拟整数Id{get;set;}
//在此处返回readonlycollection,readonlycollection实现
//IList,ICollection,IEnumerable,IList,ICollection,IEnumerable,
//因此,返回的列表可以是从这些基类型继承的任何集合类型。
公共只读集合部件
{
获取{返回新列表(_parts).AsReadOnly();}}
}
公共部分(部分)
{
//通常我不想要复制品
如果(!\u部件包含(部件))
_部分。添加(部分);
}
}

“受保护集”不会使零件集合属性为只读。它只防止外部类更改对另一个集合的引用。要使其成为只读,您必须返回一个新的ReadOnlyCollection(Parts)或返回IEnumerable(不是真正的只读,而是为API使用者提供了一个良好的指示)。有关这两种方法的含义的更多信息,请搜索,关于这一点有很多线索。哦,顺便说一下,刚刚意识到您的_parts是一个自动实现的属性,而不是一个成员变量。。。这应该改变
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);
    }
}