簡體   English   中英

流利的NHibernate正確映射基類的只讀屬性

[英]Fluent NHibernate Correctly map readonly property from base class

我想為某些實體創建基類,因為它們都共享Event列表屬性。 我還想使Event列表成為只讀屬性

因此,我創建了一個基本的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收到一個錯誤:

無法將類型為'NHibernate.Collection.Generic.PersistentGenericBag'1 [SolutionDOC_Interface.Entity.Event]'的對象強制轉換為'System.Collections.Generic.List'1 [SolutionDOC_Interface.Entity.Event]'類型的對象。

我認為這與EventRelatedEntity類沒有NHibernate映射的事實有關,但是我不能提供映射,因為它與DB中的表無關。 也許如果我在每個類(公司,文檔等)中聲明事件列表而沒有使用繼承,則NHibernate可以工作,但是這種方法會產生很多我想避免的代碼重復。

更新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();
    }

    // ...
}

使用列表接口而不是具體的列表類,則NHibernate.Collection.Generic.PersistentGenericBag應該起作用。

使用IList<Event>而不是List<Event>因此EventRelatedEntity變為:

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

    // rest of implementation...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM