Skip to content

Instantly share code, notes, and snippets.

@chilversc
Created December 31, 2015 08:59
Show Gist options
  • Save chilversc/d1ba1fdbae58d8a13704 to your computer and use it in GitHub Desktop.
Save chilversc/d1ba1fdbae58d8a13704 to your computer and use it in GitHub Desktop.
NHibernate NodaTime.OffsetDateTime
using System;
using System.Data;
using NHibernate;
using NHibernate.SqlTypes;
using NHibernate.UserTypes;
using NodaTime;
[Serializable]
public class InstantType : IUserType
{
public SqlType[] SqlTypes
{
get { return new[] {SqlTypeFactory.DateTime}; }
}
public Type ReturnedType
{
get { return typeof (Instant); }
}
public bool IsMutable
{
get { return false; }
}
public new bool Equals (object x, object y)
{
return object.Equals (x, y);
}
public int GetHashCode (object x)
{
return x == null ? 0 : x.GetHashCode ();
}
public object NullSafeGet (IDataReader rs, string[] names, object owner)
{
var value = NHibernateUtil.DateTime.NullSafeGet (rs, names);
if (value == null)
return null;
else
return Instant.FromDateTimeUtc (DateTime.SpecifyKind((DateTime) value, DateTimeKind.Utc));
}
public void NullSafeSet (IDbCommand cmd, object value, int index)
{
if (value == null)
NHibernateUtil.DateTime.NullSafeSet (cmd, null, index);
else
NHibernateUtil.DateTime.NullSafeSet (cmd, ((Instant) value).ToDateTimeUtc (), index);
}
public object DeepCopy (object value)
{
return value;
}
public object Replace (object original, object target, object owner)
{
return original;
}
public object Assemble (object cached, object owner)
{
return cached;
}
public object Disassemble (object value)
{
return value;
}
}
using NHibernate.Linq.Functions;
// Use configuration.LinqToHqlGeneratorsRegistry<LinqToHqlGeneratorsRegistry> () to register this
public class LinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
public LinqToHqlGeneratorsRegistry()
{
this.Merge (new OffsetDateTimeToInstantGenerator ());
}
}
using System.Collections.ObjectModel;
using System.Linq.Expressions;
using System.Reflection;
using NHibernate.Hql.Ast;
using NHibernate.Linq;
using NHibernate.Linq.Functions;
using NHibernate.Linq.Visitors;
using NodaTime;
// Converts OffsetDateTime.ToInstant() to use the OffsetDateTimeType's UtcDateTime property
// e.g. items.Where(x => x.Date.ToInstant() > minDate.ToInstant())
// is converted to the HQL; WHERE x.UtcDateTime > @minDate
public class OffsetDateTimeToInstantGenerator : BaseHqlGeneratorForMethod
{
public OffsetDateTimeToInstantGenerator()
{
SupportedMethods = new [] {
ReflectionHelper.GetMethodDefinition<OffsetDateTime> (x => x.ToInstant())
};
}
public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
{
var source = visitor.Visit (targetObject).AsExpression ();
var property = treeBuilder.Ident ("UtcDateTime");
return treeBuilder.Dot (source, property);
}
}
using System;
using System.Data;
using NHibernate;
using NHibernate.Engine;
using NHibernate.Type;
using NHibernate.UserTypes;
using NodaTime;
[Serializable]
public class OffsetDateTimeType : ICompositeUserType
{
private static readonly IType instantType = NHibernateUtil.Custom (typeof (InstantType));
private static readonly IType offsetType = NHibernateUtil.Custom (typeof (OffsetType));
// UtcDateTime will be available as a property for HQL queries
public string[] PropertyNames
{
get { return new[] {"UtcDateTime", "Offset"}; }
}
public IType[] PropertyTypes
{
get { return new[] {instantType, offsetType}; }
}
public Type ReturnedClass
{
get { return typeof (OffsetDateTime); }
}
public bool IsMutable
{
get { return false; }
}
public object GetPropertyValue (object component, int property)
{
var date = (OffsetDateTime) component;
switch (property) {
case 0: return date.ToInstant ();
case 1: return date.Offset;
default: throw new ArgumentOutOfRangeException ("property");
}
}
public void SetPropertyValue (object component, int property, object value)
{
throw new NotSupportedException ("OffsetDateTime is immutable");
}
public new bool Equals (object x, object y)
{
if (x == null && y == null) return true;
if (x == null || y == null) return false;
return ((OffsetDateTime) x).ToInstant () == ((OffsetDateTime) y).ToInstant ();
}
public int GetHashCode (object x)
{
return x == null ? 0 : ((OffsetDateTime) x).ToInstant ().GetHashCode ();
}
public object NullSafeGet (IDataReader dr, string[] names, ISessionImplementor session, object owner)
{
var utc = (Instant?) instantType.NullSafeGet (dr, names [0], session, owner);
var offset = (Offset?) offsetType.NullSafeGet (dr, names [1], session, owner);
if (utc == null)
return null;
else
return utc.Value.WithOffset (offset ?? Offset.Zero);
}
public void NullSafeSet (IDbCommand cmd, object value, int index, bool[] settable, ISessionImplementor session)
{
if (value == null) {
instantType.NullSafeSet (cmd, null, index, session);
offsetType.NullSafeSet (cmd, null, index + 1, session);
} else {
var date = (OffsetDateTime) value;
instantType.NullSafeSet (cmd, date.ToInstant (), index, session);
offsetType.NullSafeSet (cmd, date.Offset, index + 1, session);
}
}
public object DeepCopy (object value)
{
return value;
}
public object Disassemble (object value, ISessionImplementor session)
{
return value;
}
public object Assemble (object cached, ISessionImplementor session, object owner)
{
return cached;
}
public object Replace (object original, object target, ISessionImplementor session, object owner)
{
return original;
}
}
using System;
using System.Data;
using NHibernate;
using NHibernate.SqlTypes;
using NHibernate.UserTypes;
using NodaTime;
[Serializable]
public class OffsetType : IUserType
{
public SqlType[] SqlTypes
{
get { return new[] {SqlTypeFactory.Int16}; }
}
public Type ReturnedType
{
get { return typeof (Offset); }
}
public bool IsMutable
{
get { return false; }
}
public new bool Equals (object x, object y)
{
return object.Equals (x, y);
}
public int GetHashCode (object x)
{
return x == null ? 0 : x.GetHashCode ();
}
public object NullSafeGet (IDataReader rs, string[] names, object owner)
{
var value = NHibernateUtil.Int16.NullSafeGet (rs, names);
if (value == null)
return null;
else
return OffsetFromMinutes ((short) value);
}
public void NullSafeSet (IDbCommand cmd, object value, int index)
{
if (value == null)
NHibernateUtil.Int16.NullSafeSet (cmd, null, index);
else
NHibernateUtil.Int16.NullSafeSet (cmd, OffsetToMinutes ((Offset) value), index);
}
public object DeepCopy (object value)
{
return value;
}
public object Replace (object original, object target, object owner)
{
return original;
}
public object Assemble (object cached, object owner)
{
return cached;
}
public object Disassemble (object value)
{
return value;
}
private static Offset OffsetFromMinutes (long value)
{
return Offset.FromTicks (value * NodaConstants.TicksPerMinute);
}
private static short OffsetToMinutes (Offset value)
{
return checked ((short) (value.Ticks / NodaConstants.TicksPerMinute));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment