使用 NHibernate 和 FluentMapping 的状态模式
State pattern using NHibernate and FluentMapping
在我们的应用程序中,我们为我们的实体使用状态模式。我们有一个问题,将状态映射到数据库值。我们当前的解决方案有效,但不支持 IQueryable(来自休眠),因此迫使我们在存储库中调用 .ToList()。
这是我们的实体:
public class Gap
{
[ommited]
public virtual IGapState State { get; protected set; }
public virtual IGapState PreviousState { get; protected set; }
}
目前,我们的 IGapState 映射如下所示:
public class GapMap : ClassMap<Gap> {
[ommited]
Map(x => x.State).CustomType<GapStateType>();
Map(x => x.PreviousState).CustomType<GapPreviousStateType>()
}
我们的自定义类型如下所示:
public class GapStateType : ICompositeUserType
{
public bool IsMutable => false;
public virtual string[] PropertyNames => new string[1] { "State" };
public IType[] PropertyTypes => new IType[1] { NHibernateUtil.Int32 };
public Type ReturnedClass => typeof(IGapState);
public object Assemble(object cached, ISessionImplementor session, object owner) => cached;
public object DeepCopy(object value) => value;
public object Disassemble(object value, ISessionImplementor session) => value;
public new bool Equals(object x, object y) => object.Equals(x, y);
public int GetHashCode(object x) => x.GetHashCode();
public object GetPropertyValue(object component, int property)
{
IGapState state = (IGapState)component;
return state.Discriminator;
}
public object NullSafeGet(IDataReader dr, string[] names, ISessionImplementor session, object owner)
{
State state = (State)NHibernateUtil.Int32.NullSafeGet(dr, names[0]);
switch (state)
{
case State.New:
return new New();
case State.InProgress:
return new InProgress();
case State.TicketClosedWaitingForEvidence:
return new TicketClosedWaitingForEvidence();
case State.EvidenceProvidedWaitingForTicketClosure:
return new EvidenceProvidedWaitingForTicketClosure();
case State.EvidenceProvidedWaitingForTicketAssigment:
return new EvidenceProvidedWaitingForTicketAssigment();
case State.FalsePositiveWaitingForApproval:
return new FalsePositiveWaitingForApproval();
case State.FalsePositiveApproved:
return new FalsePositiveApproved();
case State.RiskStateWaitingForApproval:
return new RiskStateWaitingForApproval();
case State.RiskStateApproved:
return new RiskStateApproved();
case State.Closed:
return new Closed();
default:
return new Null();
}
}
public void NullSafeSet(IDbCommand cmd, object value, int index, bool[] settable, ISessionImplementor session)
{
//State state = (State)value;
//NHibernateUtil.Int32.NullSafeSet(cmd, (int)state, index);
IGapState state = (IGapState)value;
NHibernateUtil.Int32.NullSafeSet(cmd, (int)state.Discriminator, index);
}
public object Replace(object original, object target, ISessionImplementor session, object owner)
{
return target;
}
public void SetPropertyValue(object component, int property, object value)
{
throw new InvalidOperationException("Discriminator is an immutable object. SetPropertyValue isn't supported.");
}
}
在存储库中我们调用
public IEnumerable<Gap> FindWatingForApprovalRisk()
{
return FindAll().ToList().Where(x => x.State.Discriminator == State.RiskStateWaitingForApproval);
}
一切都很好,直到我们没有大量的实体。当我们删除 ToList() 并将 return 类型更改为 IQueryable 时,我们得到以下异常:
could not resolve property: State.Discriminator of:
Exprimo.CBA.Model.Entities.GapPortal.Gap
[.Count[Exprimo.CBA.Model.Entities.GapPortal.Gap]
(.Where[Exprimo.CBA.Model.Entities.GapPortal.Gap]
(NHibernate.Linq.NhQueryable`1[Exprimo.CBA.Model.Entities.GapPortal.Gap],
Quote((x, ) => (Equal(Convert(x.State.Discriminator), p1))), ), )]
NHibernate 不知道如何处理 x.State.Discriminator,因为您的映射停止在 x.State。
尝试:
.Where(x => x.State == new RiskStateWaitingForApproval())
在我们的应用程序中,我们为我们的实体使用状态模式。我们有一个问题,将状态映射到数据库值。我们当前的解决方案有效,但不支持 IQueryable(来自休眠),因此迫使我们在存储库中调用 .ToList()。
这是我们的实体:
public class Gap
{
[ommited]
public virtual IGapState State { get; protected set; }
public virtual IGapState PreviousState { get; protected set; }
}
目前,我们的 IGapState 映射如下所示:
public class GapMap : ClassMap<Gap> {
[ommited]
Map(x => x.State).CustomType<GapStateType>();
Map(x => x.PreviousState).CustomType<GapPreviousStateType>()
}
我们的自定义类型如下所示:
public class GapStateType : ICompositeUserType
{
public bool IsMutable => false;
public virtual string[] PropertyNames => new string[1] { "State" };
public IType[] PropertyTypes => new IType[1] { NHibernateUtil.Int32 };
public Type ReturnedClass => typeof(IGapState);
public object Assemble(object cached, ISessionImplementor session, object owner) => cached;
public object DeepCopy(object value) => value;
public object Disassemble(object value, ISessionImplementor session) => value;
public new bool Equals(object x, object y) => object.Equals(x, y);
public int GetHashCode(object x) => x.GetHashCode();
public object GetPropertyValue(object component, int property)
{
IGapState state = (IGapState)component;
return state.Discriminator;
}
public object NullSafeGet(IDataReader dr, string[] names, ISessionImplementor session, object owner)
{
State state = (State)NHibernateUtil.Int32.NullSafeGet(dr, names[0]);
switch (state)
{
case State.New:
return new New();
case State.InProgress:
return new InProgress();
case State.TicketClosedWaitingForEvidence:
return new TicketClosedWaitingForEvidence();
case State.EvidenceProvidedWaitingForTicketClosure:
return new EvidenceProvidedWaitingForTicketClosure();
case State.EvidenceProvidedWaitingForTicketAssigment:
return new EvidenceProvidedWaitingForTicketAssigment();
case State.FalsePositiveWaitingForApproval:
return new FalsePositiveWaitingForApproval();
case State.FalsePositiveApproved:
return new FalsePositiveApproved();
case State.RiskStateWaitingForApproval:
return new RiskStateWaitingForApproval();
case State.RiskStateApproved:
return new RiskStateApproved();
case State.Closed:
return new Closed();
default:
return new Null();
}
}
public void NullSafeSet(IDbCommand cmd, object value, int index, bool[] settable, ISessionImplementor session)
{
//State state = (State)value;
//NHibernateUtil.Int32.NullSafeSet(cmd, (int)state, index);
IGapState state = (IGapState)value;
NHibernateUtil.Int32.NullSafeSet(cmd, (int)state.Discriminator, index);
}
public object Replace(object original, object target, ISessionImplementor session, object owner)
{
return target;
}
public void SetPropertyValue(object component, int property, object value)
{
throw new InvalidOperationException("Discriminator is an immutable object. SetPropertyValue isn't supported.");
}
}
在存储库中我们调用
public IEnumerable<Gap> FindWatingForApprovalRisk()
{
return FindAll().ToList().Where(x => x.State.Discriminator == State.RiskStateWaitingForApproval);
}
一切都很好,直到我们没有大量的实体。当我们删除 ToList() 并将 return 类型更改为 IQueryable 时,我们得到以下异常:
could not resolve property: State.Discriminator of:
Exprimo.CBA.Model.Entities.GapPortal.Gap
[.Count[Exprimo.CBA.Model.Entities.GapPortal.Gap]
(.Where[Exprimo.CBA.Model.Entities.GapPortal.Gap]
(NHibernate.Linq.NhQueryable`1[Exprimo.CBA.Model.Entities.GapPortal.Gap],
Quote((x, ) => (Equal(Convert(x.State.Discriminator), p1))), ), )]
NHibernate 不知道如何处理 x.State.Discriminator,因为您的映射停止在 x.State。
尝试:
.Where(x => x.State == new RiskStateWaitingForApproval())