2017-10-10 6 views
0

私のエンティティのいくつかは、すべてがEventリストプロパティを共有しているため、基本クラスを作成したいと思います。 Eventリストを読み取り専用プロパティにしたいと考えています。Fluent NHibernate基本クラスのreadonlyプロパティを正しくマップします

私はベースEventRelatedEntityクラスを作成し、それをイベントと関係があるエンティティクラスごとに派生させました。

また、テーブルにリンクされていないので、EventRelatedEntityクラスにはNHibernateマッピングクラスはありません。

以下のコードを参照してください。

基本クラス:

public class EventRelatedEntity 
{ 
    private readonly List<Event> events; 

    public virtual IReadOnlyCollection<Event> Events { get; protected set; } 

    public EventRelatedEntity() 
    { 
     events = new List<Event>(); 
     Events = events.AsReadOnly(); 
    } 

    protected virtual void AddEvent<T>(T entity, string message) 
    { 
     if (events == null) 
      events = new List<Event>(); 

     Event newEvent = new Event(); 

     if (typeof(T) == typeof(Company)) 
     { 
      newEvent.CompanyId = (entity as Company).Id; 
      // ...and do some other stuff... 
     } 
     else if (typeof(T) == typeof(Document)) 
     { 
      newEvent.DocumentId = (entity as Document).Id; 
      // ...and do some other stuff... 
     } 
     else if (typeof(T) == typeof(Typology)) 
     { 
      newEvent.TypologyId = (entity as Typology).Id; 
      // ...and do some other stuff... 
     } 

     newEvent.Message = message; 

     events.Add(newEvent); 
    } 
} 

エンティティクラス

public class Company : EventRelatedEntity 
{ 
    [Key] 
    public virtual int Id { get; protected set; } 
    [Required] 
    public virtual string Alias { get; set; } 
    [Required] 
    public virtual string CompanyName { get; set; } 
    // ...and some other properties... 

    #region Actions 

    public virtual void AddEvent(string message) 
    { 
     base.AddEvent(this, message); 
    } 

    #endregion 
} 

public class Document : EventRelatedEntity 
{ 
    [Key] 
    public override int Id { get; protected set; } 
    [Required] 
    public virtual User User { get; protected set; } 
    // ...and some other properties... 

    #region Actions 

    public virtual void AddEvent(string message) 
    { 
     base.AddEvent(this, message); 
    } 

    #endregion 
} 

// ...and some other classes... 

エンティティのため流暢NHibernateのマッピングクラス

public class CompanyMap : ClassMap<Company> 
{ 
    public CompanyMap() 
    { 
     Table("Companies"); 
     LazyLoad(); 
     Id(x => x.Id).GeneratedBy.Identity().Column("Id"); 
     Map(x => x.Alias).Column("Alias").Not.Nullable(); 
     Map(x => x.CompanyName).Column("CompanyName").Not.Nullable(); 
     // ...and some other mappings... 

     // Link with Events table 
     HasMany(x => x.Events) // Events is declared in the base class (EventRelatedEntity) 
      .KeyColumn("CompanyId") 
      .Access.LowerCaseField() 
      .Cascade.AllDeleteOrphan(); 
    } 
} 

public class DocumentMap : ClassMap<Document> 
{ 
    public DocumentMap() 
    { 
     Table("Documents"); 
     LazyLoad(); 
     Id(x => x.Id).GeneratedBy.Identity().Column("Id"); 
     References(x => x.User).Column("UserId"); 
     // ...and some other mappings... 

     // Link with Events table 
     HasMany(x => x.Events) // Events is declared in the base class (EventRelatedEntity) 
      .KeyColumn("DocumentId") 
      .Access.LowerCaseField() 
      .Cascade.AllDeleteOrphan(); 
    } 
} 

// ...and some other mapping classes... 

最後に、List<>.Add()メソッドへの直接アクセスを避けたいと思います。私は読み取り専用のコレクションが欲しい。新しいEventをエンティティのイベントリストに追加する唯一の方法は、対応するエンティティクラスのAddEventメソッドでなければなりません。

例:

Document document = session.Get<Document>(1); 
// ...the same for other derived classes... 

// I WANT TO AVOID THIS! 
document.Events.Add(new Event()); 
// WANTS TO BE THE ONLY PERMITTED WAY TO ADD NEW EVENTS 
document.AddEvent("My new event message"); 

問題は、私がやるときということです:

Document document = session.Get<Document>(1); 

私はNHibernateのからのエラーを取得:

Cannot cast objects of type 'NHibernate.Collection.Generic.PersistentGenericBag'1 [SolutionDOC_Interface.Entity.Event]' to the 'System.Collections.Generic.List'1 [SolutionDOC_Interface.Entity.Event]' type.

私はそれはと関連していると思います実際にはEventRelatedEntityクラスはNHibernateマッピングを持っていませんが、マップを提供することはできません。 o DB内の表を使用します。 継承を使わずに各クラス(Company、Documentなど)の中でイベントリストを宣言した場合、NHibernateは機能しますが、このアプローチでは避けたいコードの複製がかなり生成されます。 @ryanのようなコードを変更した後

UPDATE 2017年10月18日

は、それが動作するようになりまし提案。

改訂コード:

public class EventRelatedEntity 
{ 
    private readonly IList<Event> events; 

    public virtual IReadOnlyCollection<Event> Events { get; protected set; } 

    public EventRelatedEntity() 
    { 
     events = new List<Event>(); 
     Events = (events as List<Event>).AsReadOnly(); 
    } 

    // ... 
} 
+0

ような問題をいただきましたか!?もし 'Events'が本当に' IReadOnlyCollection'として宣言されていれば 'document.Events.Add(new Event());'はエラーを生成しているはずです: ''IReadOnlyCollection 'は' Add 'の定義を含んでいません。 " – ryan

+0

NHibernateエラーが発生しました。私は質問を更新しました。 –

答えて

1

その後、NHibernate.Collection.Generic.PersistentGenericBagのキャストが動作するはずです、代わりに具体的なリストクラスのリストインターフェースを使用してください。

利用IList<Event>代わりのList<Event>のでEventRelatedEntityは次のようになります。

public class EventRelatedEntity 
{ 
    private readonly IList<Event> events; 

    // rest of implementation... 
} 
関連する問題