代码之家  ›  专栏  ›  技术社区  ›  Jakub Z.

使用NHibernate和FluentMapping的状态模式

  •  -1
  • Jakub Z.  · 技术社区  · 7 年前

    这是我们的实体:

    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()并将返回类型更改为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))), ), )]
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   ErikKolo    7 年前

    NHibernate不知道如何处理x.State。鉴别器,因为映射在x.State处停止。

    尝试:

    .Where(x => x.State == new RiskStateWaitingForApproval())