2011-01-31 109 views
0

如何使用約定來映射零件集合?如何映射通過只讀屬性訪問的集合?

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'" 

回答

0

首先,你_parts成員不能是隻讀的。 NHibernate需要寫訪問權限來設置值/引用。要通過Parts屬性返回真正的只讀集合,必須返回一個System.Collections.ObjectModel.ReadOnlyCollection。如果你只是返回f.ex,這也「刪除」在讀/寫集合類型中找到的所有方法。 list.AsReadOnly()。以這種方式返回一個只讀列表仍然有。新增()方法和其他編輯的最愛,但它們將導致運行時異常所以返回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); 

Example類:

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); 
    } 
} 
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」作爲一個鉤子,以便您可以填充列表。

+0

「保護套」 不將使Parts Collection屬性爲只讀。它只會阻止外部類將引用更改爲另一個集合。爲了使它成爲只讀,你必須返回一個新的ReadOnlyCollection(Parts)或者返回IEnumerable(不是真正的只讀,但是給API消費者一個很好的指示)。有關這兩種方式的含義的更多信息,搜索SO,有許多關於此的線程。 – Trygve 2011-05-24 06:19:01

相關問題