具有实体框架的状态模式

时间:2013-07-01 12:26:51

标签: asp.net-mvc entity-framework design-patterns

我有一个模型Enquiry,它可以处于两种状态之一(还有更多,但出于此目的,我只会比较两种状态):NewClosed。查询所处的状态取决于用户能够对查询进行的操作。例如,无法删除已关闭的查询,因为新查询可以删除等等(基本示例)。

我想用Entity Framework来坚持这一点但不确定如何。以下是我的代码。

询问:

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");
    }
}

所以我的问题是,我不确定如何将这些不同的状态存储在数据库中,我是否应该在每个状态上使用某种int字段并通过一个状态将它们映射到Enquiry FK?另外,我是否还需要将字段CanAddLinesCanDelete映射到数据库?看到逻辑包含在状态中,对于状态模式范例来说还是新的

1 个答案:

答案 0 :(得分:3)

您的州没有任何数据存储。所以,实际上你只需要存储状态类型:

[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);
    }
}

顺便说一下,如果抽象类虚拟成员已经返回了您需要的内容(例如CanAddLinesCanDelete的{​​{1}}属性),则无需覆盖它们。