2017-10-10 147 views
0

我想爲我的一些實體創建一個基類,因爲它們都共享一個Event列表屬性。 我也想使Event列表只讀屬性流利NHibernate正確地將只讀屬性映射到基類

所以我創建了一個基類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映射,但我無法提供映射,因爲它沒有d o用DB中的表格。 也許如果我在每個類(公司,文檔等)內部聲明事件列表而不使用繼承,NHibernate就可以工作,但是這種方法會產生很多我想避免的代碼重複。

UPDATE 2017/10/18

改變這樣的代碼@ryan建議後,現在它的工作原理。

修改後的代碼:

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... 
}