9
votes

Utilisation de NHibernate ICOMPOSITEUSERType avec un type de valeur

J'ai un objet de modèle de domaine qui possède des propriétés de type system.dateTimeOffset. J'utilise une base de données qui ne supporte pas ce type de manière nativement, alors je prévois de le stocker à l'aide d'une colonne de type 'DateTime' et d'un type "Smallint".

J'ai creusé sur la manière de cartographier ceci à l'aide de composants NHibernate et a constaté que cela pourrait fonctionner à l'aide d'une instance ICOMPOSITEUSERType. Toutefois, lors de la mise en œuvre de l'interface, j'ai rencontré la méthode appelée "SetPropertyValue" qui définit ostensiblement une propriété dans le type. Puisque DateTimeOffset est un système.ValueType, il suffit de définir une propriété comme celle-ci fonctionnera car elle est immuable (au moins, sans utiliser de réflexion ou de code dangereux, que je voudrais éviter). Étant donné que le paramètre d'instance sur SetPropertyValue n'est pas "Réf 'Comment utiliser l'inconvénient-tutype en tant que composants dans NHibernate?


0 commentaires

3 Réponses :


0
votes
// code to calculate hours, minutes, seconds from object value
DateTime dt = (DateTime)component;
dt = new DateTime(dt.Year, dt.Month, dt.Day, hours, minutes, seconds);

4 commentaires

Ok, assez juste ... je suis jusqu'à présent. Mais comment votre instance "DT" est-elle revenue au modèle de domaine?


DT = composant, simplement cassette à DateTime. Je pourrais le remplacer partout avec ((DateTime) composant). Le composant est ce qui est réellement donné au modèle de domaine.


Je ne suis pas sûr de la documentation de ce genre de choses. Je ne me souviens même pas de cela et je devais regarder le contexte de mon code. Je pense que je devais regarder l'exemple habituellement fourni avec NHibernate (Deux TwoStrings, je pense?) Et apprendre de cela (et l'oublie évidemment une fois que j'ai été fait!)


Je suis juste déconcerté sur la façon dont vous pourriez obtenir cela pour le travailler, car DateTime est un apprécipé. Dès que vous le compromettez à la section locale «DT», vous en effectuez une copie et toutes les modifications sont perdues dès que la méthode sort. C'est le creux de mon problème avec la méthode SetPropertyValue. Il n'y a aucun moyen d'obtenir un apprécipé de celui-ci.



2
votes

Je crois comprendre que si le type que vous mappiez avec et icomPositeUserSerType est immuable, SetPropertyValue () ne devrait rien faire du tout, ni même lancer une exception, car NHibernate ne devrait pas l'appeler.


0 commentaires

6
votes

rendre le type d'utilisateur immuable en retournant false in is-mutable code> et juste lancer une exception dans setpropertyvalue code>.

J'ai quelque chose de similaire, mais avec un propre type de données au lieu de DateTimeOffset code>. Je viens de adapter le code pour vous. Il stocke la date d'heure UTC et le décalage comme Timespan code> (stocke des ticks. Bien sûr, vous n'avez pas besoin de cette résolution. Mais vous ne devez pas stocker des heures entières pour les fuseaux horaires, il y a Les zones de temps décalent avec des fractions d'heures strong> !! et tispan code> sont construits dans des travaux hors de la boîte.) p>

public class DateTimeOffsetUserType : ICompositeUserType
{
    public bool IsMutable
    {
        get { return false; }
    }

    public void SetPropertyValue(object component, int property, object value)
    {
        throw new InvalidOperationException("Immutable, SetPropertyValue is not allowed");
    }

    public object NullSafeGet(System.Data.IDataReader dr, string[] names, NHibernate.Engine.ISessionImplementor session, object owner)
    {
        if (dr == null)
        {
            return null;
        }

        DateTime? utcTime;
        TimeSpan? offset;

        utcTime = (DateTime?)PropertyTypes[0].NullSafeGet(dr, names[0], session, owner);
        offset = (TimeSpan?)PropertyTypes[1].NullSafeGet(dr, names[1], session, owner);

        if (utcTime == null || offset == null) return null;
        return new DateTimeOffset(utcTime.Value, offset.Value);
    }

    public void NullSafeSet(System.Data.IDbCommand cmd, object value, int index, NHibernate.Engine.ISessionImplementor session)
    {
        if (value == null)
        {
            NHibernateUtil.Timestamp.NullSafeSet(cmd, null, index);
            NHibernateUtil.TimeSpan.NullSafeSet(cmd, null, index + 1);
        }
        else
        {
            DateTimeOffset dateTimeOffset = (DateTimeOffset)value;

            PropertyTypes[0].NullSafeSet(cmd, dateTimeOffset.UtcDateTime, index, session);
            PropertyTypes[1].NullSafeSet(cmd, dateTimeOffset.Offset, index + 1, session);
        }

    }

    // other methods


0 commentaires