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