1

I'm having problems mapping a relationaship between two entities when there are two columns involved in the mapping.

I'm modelling a state machine with two object types - State and Transition. Each process has its own state machine, so States and Transitions need to be identified by ProcessId. My entity classes are like this:

public class State
{
    public virtual long Id { get; set; }
    public virtual int ProcessId { get; set; }
    public virtual int Ordinal { get; set; }

    public virtual Process Process { get; set; }
    public virtual ICollection<Transition> TransitionsIn { get; set; }
    public virtual ICollection<Transition> TransitionsOut { get; set; }
}

public class Transition
{
    public virtual long Id { get; set; }
    public virtual long ProcessId { get; set; }
    public virtual int FromStateNum { get; set; }
    public virtual int ToStateNum { get; set; }
    public virtual long StateActionId { get; set; }

    public virtual Process Process { get; set; }
    public virtual StateAction StateAction { get; set; }
    public virtual State FromState { get; set; }
    public virtual State ToState { get; set; }
}

I need the navigation properties (State.TransitionsIn, State.TransitionsOut, Transition.FromState, Transition.ToState) to be based on the ProcessId and the Ordinal number of the state. For example, Transition.FromState should navigate to the entity where t.ProcessId = s.ProcessId and t.FromStateNum = s.Ordinal.

I've tried the following mapping, but it complains that I'm using two columns to map to one (StateId).

public class StateMap : ClassMap<State>
{
    public StateMap()
    {
        Id(x => x.Id);
        HasMany(s => s.TransitionsIn)
            .KeyColumns.Add("ProcessId", "ToStateNum")
            .Inverse();
        HasMany(s => s.TransitionsOut)
            .KeyColumns.Add("ProcessId", "FromStateNum")
            .Inverse();
    }
}

public class TransitionMap : ClassMap<Transition>
{
    public TransitionMap()
    {
        Id(x => x.Id);
        References(t => t.FromState)
            .Columns("ProcessId", "Ordinal");
        References(t => t.ToState)
            .Columns("ProcessId", "Ordinal");
    }
}

How can I get this to work?

1 Answer 1

1

How about this mapping.. I have not tested it but just trying to give a direction.

public class StateMap : ClassMap<State>
{
    public StateMap()
    {
        Id(x => x.Id);
        HasMany(s => s.TransitionsIn)
            .KeyColumn("ProcessId")
            .KeyColumn("ToStateNum").PropertyRef("Ordinal")
            .Inverse();

        HasMany(s => s.TransitionsOut)
            .KeyColumn("ProcessId")
            .KeyColumn("FromStateNum").PropertyRef("Ordinal")
            .Inverse();
    }
}

public class TransitionMap : ClassMap<Transition>
{
    public TransitionMap()
    {
        Id(x => x.Id);
        References(t => t.FromState)
            .Columns("ProcessId", "FromStateNum");
        References(t => t.ToState)
            .Columns("ProcessId", "ToStateNum");
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

I've solved the problem a different way using a surrogate key - probably the right way. I haven't had the chance to test your answer, but I'll give you the kudos anyway. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.