Comment mapper-vous une propriété DateTime 2 colonnes varchar dans la base de données avec NHibernate (Courant)?
-
22-09-2019 - |
Question
Je fais face à une base de données existante qui a champs date et heure comme char (8) colonnes (AAAAMMJJ et HH format: mm: ss respectivement) dans certains des tableaux. Comment puis-je mapper les 2 colonnes char à une seule propriété DateTime .NET? J'ai essayé ce qui suit, mais je reçois une erreur bien sûr « ne peut pas accéder setter » parce que les propriétés DateTime Date et timeofday sont en lecture seule:
public class SweetPocoMannaFromHeaven
{
public virtual DateTime? FileCreationDateTime { get; set; }
}
.
mapping.Component<DateTime?>(x => x.FileCreationDateTime,
dt =>
{
dt.Map(x => x.Value.Date,
"file_creation_date");
dt.Map(x => x.Value.TimeOfDay,
"file_creation_time");
});
J'ai aussi essayé de définir un IUserType pour DateTime, mais je ne peux pas le comprendre. Je l'ai fait une tonne de googler pour une réponse, mais je ne peux pas le comprendre encore. Quelle est ma meilleure option pour gérer cette stupide Convention de base de données existante? Un exemple de code serait utile car il n'y a pas grand-chose pour la documentation sur certains de ces scénarios les plus obscurs.
La solution
Vous avez besoin d'un ICompositeUserType pour traiter plus d'une colonne. Vous avez besoin de renforcer le contrôle d'erreur, formats analyse, etc, mais voici un point de départ pour vous.
HTH,
Berryl
public class LegacyDateUserType : ICompositeUserType
{
public new bool Equals(object x, object y)
{
if (x == null || y == null) return false;
return ReferenceEquals(x, y) || x.Equals(y);
}
public int GetHashCode(object x) {
return x == null ? typeof (DateTime).GetHashCode() + 473 : x.GetHashCode();
}
public object NullSafeGet(IDataReader dr, string[] names, ISessionImplementor session, object owner)
{
if (dr == null) return null;
var datePortion = NHibernateUtil.String.NullSafeGet(dr, names[0], session, owner) as string;
var timePortion = NHibernateUtil.String.NullSafeGet(dr, names[1], session, owner) as string;
var date = DateTime.Parse(datePortion);
var time = DateTime.Parse(timePortion);
return date.AddTicks(time.Ticks);
}
///<summary>
/// Write an instance of the mapped class to a prepared statement. Implementors
/// should handle possibility of null values. A multi-column type should be written
/// to parameters starting from index.
///</summary>
public void NullSafeSet(IDbCommand cmd, object value, int index, ISessionImplementor session) {
if (value == null) {
// whatever
}
else {
var date = (DateTime) value;
var datePortion = date.ToString("your date format");
NHibernateUtil.String.NullSafeSet(cmd, datePortion, index, session);
var timePortion = date.ToString("your time format");
NHibernateUtil.String.NullSafeSet(cmd, timePortion, index + 1, session);
}
}
public object GetPropertyValue(object component, int property)
{
var date = (DateTime)component;
return property == 0 ? date.ToString("your date format") : date.ToString("your time format");
}
public void SetPropertyValue(object component, int property, object value)
{
throw new NotSupportedException("DateTime is an immutable object.");
}
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; }
///<summary>Get the "property names" that may be used in a query.</summary>
public string[] PropertyNames { get { return new[] { "DATE_PORTION", "TIME_PORTION" }; } }
///<summary>Get the corresponding "property types"</summary>
public IType[] PropertyTypes { get { return new IType[] { NHibernateUtil.String, NHibernateUtil.String }; } }
///<summary>The class returned by NullSafeGet().</summary>
public Type ReturnedClass { get { return typeof(DateTime); } }
///<summary>Are objects of this type mutable?</summary>
public bool IsMutable { get { return false; } }
}
=== mappage courant (en supposant AutoMapping w / catégories de remplacement) ====
public void Override(AutoMapping<MyClass> m)
{
....
m.Map(x => x.MyDateTime).CustomType<LegacyDateUserType>();
}