2017-10-10 158 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... 
}