2017-09-29 2 views
0

Dans notre appliacion, nous utilisons un modèle d'état pour nos entités. Nous avons un problème avec le mappage de l'état à la valeur de la base de données. Notre solution actuelle fonctionne, mais ne supporte pas IQueryable (à partir d'hibernate), nous forçant ainsi à appeler .ToList() dans les dépôts.Modèle d'état utilisant NHibernate et FluentMapping

Voici notre entité:

public class Gap 
{ 
    [ommited] 

    public virtual IGapState State { get; protected set; } 
    public virtual IGapState PreviousState { get; protected set; } 
} 

Actuellement, notre correspondance pour IGapState ressemble à ceci:

public class GapMap : ClassMap<Gap> { 
    [ommited] 

    Map(x => x.State).CustomType<GapStateType>(); 
    Map(x => x.PreviousState).CustomType<GapPreviousStateType>() 
} 

Et notre type personnalisé pour cela ressemble à ceci:

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

Dans le référentiel nous appelons

public IEnumerable<Gap> FindWatingForApprovalRisk() 
{ 
    return FindAll().ToList().Where(x => x.State.Discriminator == State.RiskStateWaitingForApproval); 
} 

Ce qui est très bien, jusqu'à ce que nous ne disposons pas d'une grande quantité d'entités. Lorsque nous avons découpé ToList() et modifier le type de retour à IQueryable nous obtenons l'exception suivante:

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))),),)] 

Répondre

0

NHibernate ne sait pas quoi faire avec x.State.Discriminator, parce que votre cartographie arrête à x.State.

Essayez:

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