Question

I have a model Enquiry, which can be in one of two states (there are more but for the purposes of this I will just compare two): New and Closed. The state the enquiry is in is dependant upon what a user is able to do with an enquiry. For example a closed enquiry cannot be deleted where as a new enquiry is able to be deleted and so forth (basic example).

I am wanting to persist this with Entity Framework but not sure how. Below is my code.

Enquiry:

public class Enquiry
{
    public int Id { get; set; }
    public string CustomerAccountNumber { get; set; }

    public EnquiryState CurrentState { get; set; }
    public bool CanAddLines { get { return CurrentState.CanAddLines; } }
    public bool CanDelete { get { return CurrentState.CanDelete; } }

    public void ChangeState(EnquiryState currentState)
    {
        CurrentState = currentState;
    }

    public void CloseEnquiry()
    {
        CurrentState.CloseEnquiry();
    }

    /* More methods to change state here */

    public Enquiry()
    {
        CurrentState = new NewEnquiryState(this);
    }
}

EnquiryState:

public abstract class EnquiryState
{
    internal readonly Enquiry CurrentEnquiry;

    protected EnquiryState(Enquiry currentEnquiry)
    {
        CurrentEnquiry = currentEnquiry;
    }

    public virtual bool CanDelete
    {
        get { return false; }
    }

    public virtual bool CanAddLines
    {
        get { return false; }
    }

    /* More properties here */

    public abstract void CloseEnquiry();

    /* More states here */
}

NewEnquiryState:

public class NewEnquiryState : EnquiryState
{
    public NewEnquiryState(Enquiry enquiry) : base(enquiry) { }

    public override bool CanDelete
    {
        get { return true; }
    }

    public override bool CanAddLines
    {
        get { return true; }
    }

    /* ... */

    public override void CloseEnquiry()
    {
        CurrentEnquiry.ChangeState(new CloseEnquiryState(CurrentEnquiry));
    }

    /* ... */
}

CloseEnquiryState:

public class CloseEnquiryState : EnquiryState
{
    public CloseEnquiryState(Enquiry enquiry) : base(enquiry) { }

    public override bool CanAddLines
    {
        get { return false; }
    }
    public override bool CanDelete
    {
        get { return false; }
    }

    /* ... */

    public override void CloseEnquiry()
    {
        throw new Exception("Closed Enquiry can't be closed");
    }
}

So my question is, I'm not sure how to store these different states in a database, should I use some sort of int field on each state and map them to the Enquiry via an FK? Also, do I need to map the fields CanAddLines and CanDelete to a database too? Seeing as the logic is contained within the state, quite new to the state pattern paradigm

Était-ce utile?

La solution

Your state does not have any data to be stored. So, actually you need to store only state type:

[NotMapped]
public EnquiryState CurrentState { get; set; }

public int StateType
{
    get 
    {
       // get value based on CurrentState
       return (CurrentState is NewEnquiryState) ? 0 : 1;
    }
    set
    {
        // create EnquireState based on value
        CurrentState = value == 0 ? 
            (EnquiryState)new NewEnquiryState(this) : 
            (EnquiryState)new CloseEnquiryState(this);
    }
}

BTW you don't need to override abstract class virtual members if they are already return what you need (e.g. CanAddLines and CanDelete properties of CloseEnquiryState)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top