我目前正在使用 MVC 3 开发一个项目。我已经分离了我的关注点,所以有诸如核心、存储库、UI、服务等项目。我已经实现了存储库、UnitOfWork 和最重要的状态模式。
我正在使用 Entity Framework 4.3 来保存我的数据,但我遇到了一个相当烦人的情况,涉及到当前状态的持久化。以下是一些类示例:
public class Request
{
public int RequestId { get; set; }
public State CurrentState { get; set; }
}
public abstract class State
{
[Key]
public string Name {get; set;}
public virtual void OpenRequest(Request request)
{}
public virtual void CloseRequest(Request request)
{}
}
public class RequestIsOpenState : State
{
public RequestIsOpenState()
{
this.Name = "Open";
}
public override void CloseRequest(Request request)
{
request.CurrentState = new RequstIsClosedState();
}
}
public class RequestIsClosedState : State
{
public RequestIsClosedState()
{
this.Name = "Closed";
}
public override void OpenRequest(Request request)
{
request.CurrentState = new RequstIsOpenState();
}
}
使用上面的示例,我会得到一个主键冲突异常,因为它试图在 States 表中创建一个新状态。
因为状态更改是在域层内完成的,所以我不能只是从存储库中“获取”状态并通过执行以下操作使用外键设置它:
Request request = unitOfWork.RequestRepository.Find(1);
request.CurrentState = unitOfWork.StateRepository.Find("Closed");
我知道我可以选择不映射状态属性,并在请求类中保留一个字符串属性,然后在实体被水合时通过工厂在获取和设置时来回转换它们(参见 this answer ).
我想要做的就是持久化状态类,因此当返回请求时,我可以立即访问状态方法,而不会为了处理一个持久性问题而让大量 EF 东西污染我的域层。另一个好处是它给我带来了额外的好处,即在 SQL 中有一个表来查询已知状态。
最佳答案
我认为您可以通过缓存只创建一次的 State 实例来改进它,以避免每次都创建列表并避免 foreach:
public static class StateFactory
{
private static Dictionary<string, State> statesCache = FindAllDerivedStates();
public static State GetState(string stateTypeName)
{
return statesCache[stateTypeName];
}
private static Dictionary<string, State> FindAllDerivedStates()
{
var derivedType = typeof(State);
var assembly = Assembly.GetAssembly(typeof(State));
return assembly.GetTypes().Where(t => t != derivedType && derivedType.IsAssignableFrom(t))
.Select(t => (State)Activator.CreateInstance(t))
.ToDictionary(k => k.Name);
}
}
关于c# - 使用 Entity Framework 持久化状态模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21784457/