简体   繁体   中英

fluent nhibernate many-to-many with a following many-to-many mapping

I have a many-to-many hierarchical situation I just can't figure out how to solve mapping wise.

I have an entity Incident. This Incident can have many Events. An event is nothing but a value object so i created a many-to-many mapping which works perfectly fine.

Now comes the bit i cant figure out... Every Event selected for an Incident can have multiple Causes (which is a value object as well)

Below is the simplified datamodel (events and causes are both stored in SystemValues and have Type as their discriminatorvalue): 在此输入图像描述

(ID in table IncidentEvent is a surrogate primary key to avoid hassle with a composite key)

My mapping is as follows (simplified): Incident:

public class IncidentMap : ClassMap<Incident> {

    public IncidentMap() {
    Table("Incident");
    Id(x => x.ID).GeneratedBy.Identity();

        HasManyToMany(x => x.Event)
        .Table("IncidentEvent")
        .ParentKeyColumn("IncidentID")
        .ChildKeyColumn("EventID");
    }
}

Event (subclassmapped from a general 'SystemValueMap'):

public class EventMap : SubclassMap<StoryWhere> {
    public EventMap() {
        DiscriminatorValue((int)SystemValue.Type.Event);
        HasManyToMany(x => x.Incident)
        .Table("IncidentEvent")
        .ParentKeyColumn("IncidentID")
        .ChildKeyColumn("EventID");

        HasManyToMany(x => x.Cause)
            .Table("IncidentEventCause")
            .ParentKeyColumn("IncidentEventID")
            .ChildKeyColumn("CauseID");
    }
}

Cause:

public class CauseMap : SubclassMap<Cause> { 
    public CauseMap() { DiscriminatorValue((int)SystemValue.Type.Cause); }
}

As you can see the mapping for 'Event' is a mess and of course it doesnt work. When an insert is done, I get foreignkey contraints as NHibernate tries to insert EventID into columns IncidentEventID of table IncidentEventCause. I probably need to tell Nhibernate how to use IncidentEventID instead. I need to make the Event be aware of it's many-to-many relation with incident and of it's following relation with Cause, but I'm afraid I don't know how.

Hoping someone can point me in the right direction.

if possible you should refactor the database schema and exchange IncidentEventId with EventId in the table IncidentEventCause.

The mapping you want is not easily possible. Here a workaround where the persistence leaks into the domain.

public class IncidentMap : ClassMap<Incident>
{
    public IncidentMap()
    {
        Id(x => x.ID).GeneratedBy.Identity();

        HasManyToMany(x => x.Events)
            .Table("IncidentEvent")
            .ParentKeyColumn("IncidentID")
            .ChildKeyColumn("EventID")
            .ChildWhere("type=" + (int)SystemValue.Type.Event);
    }
}

public class Event
{
    private EventDetails Details { get; set; }
    public string Name { get { return Details.Name; } set { Details.Name = value; } }

}

class EventDetails : SystemValue
{
    public virtual string Name { get; set; }
}

public class EventMap : ClassMap<Event>
{
    public EventMap()
    {
        Table("IncidentEvent");

        Id(x => x.Id, "Id").GeneratedBy.Identity();

        References(x => x.Incident, "IncidentID");
        References(Reveal.Member<Event>("Details"), "EventID").Not.LazyLoad();

        HasManyToMany(x => x.Causes)
            .Table("IncidentEventCause")
            .ParentKeyColumn("IncidentEventID")
            .ChildKeyColumn("CauseID");
    }
}

public class EventDetailsMap : SubclassMap<EventDetails>
{
    public EventDetailsMap()
    {
        DiscriminatorValue((int)SystemValue.Type.Event);
        Map(x => x.Name);
    }
}

public class CauseMap : SubclassMap<Cause>
{
    public CauseMap()
    {
        DiscriminatorValue((int)SystemValue.Type.Cause);
        Map(x => x.Name);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM