实体框架的状态模式

Cal*_*ass 5 asp.net-mvc design-patterns entity-framework state-pattern

我有一个模型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);
    }
}
Run Code Online (Sandbox Code Playgroud)

查询状态:

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 */
}
Run Code Online (Sandbox Code Playgroud)

新查询状态:

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

    /* ... */
}
Run Code Online (Sandbox Code Playgroud)

关闭查询状态:

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Ser*_*kiy 4

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

[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);
    }
}
Run Code Online (Sandbox Code Playgroud)

CanAddLines顺便说一句,如果抽象类虚拟成员已经返回您需要的内容(例如和CanDelete的属性CloseEnquiryState),则不需要覆盖它们