【问题标题】:State Pattern with Entity Framework实体框架的状态模式
【发布时间】:2013-07-01 12:26:51
【问题描述】:

我有一个模型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);
    }
}

查询状态:

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 */
}

新查询状态:

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

    /* ... */
}

关闭查询状态:

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 字段并通过 FK 将它们映射到 Enquiry?另外,我还需要将字段CanAddLinesCanDelete 映射到数据库吗?看到逻辑包含在状态中,对于状态模式范式来说是全新的

【问题讨论】:

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


    【解决方案1】:

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

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

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

    【讨论】:

    • 我实际上有更多的状态,正如我所说的,我只使用了两个来简化这个例子,那么我如何使用StateType 属性来考虑呢?
    • @BiffBaffBoff 你可以从简单的开关块开始,它会根据值返回状态。或者您可以将此逻辑移至某个状态工厂。您还可以将状态类型封装在状态对象中。因此,根据当前状态获取价值将类似于 return CurrentState.Type
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-30
    • 2015-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多