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
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
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With