Reputation: 11448
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
Upvotes: 5
Views: 1976
Reputation: 236228
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
)
Upvotes: 4