2009-07-27 9 views
9

Mam obiekt modelu domeny, który ma właściwości typu System.DateTimeOffset. Używam bazy danych, która nie obsługuje tego typu natywnie, więc planuję przechowywać ją przy użyciu kolumny typu "datetime" i jednego typu "smallint".Używanie NHibernate ICompositeUserType z typem wartości

Sprawdziłem, jak zmapować to za pomocą składników NHibernate, i okazało się, że może działać przy użyciu instancji ICompositeUserType. Jednak po implementacji interfejsu natknąłem się na metodę o nazwie "SetPropertyValue", która ostentacyjnie ustawia właściwość w typie. Ponieważ DateTimeOffset to System.ValueType, samo ustawienie takiej właściwości nie zadziała, ponieważ jest niezmienne (przynajmniej bez użycia refleksji lub niebezpiecznego kodu, którego chciałbym uniknąć). Ponieważ parametr instance w SetPropertyValue nie ma wartości "ref", jak używać instancji ValueType jako komponentów w NHibernate?

Odpowiedz

6

Wprowadź typ użytkownika niezmiennego, zwracając wartość false w IsMutable i po prostu wyślij wyjątek w SetPropertyValue.

Mam coś podobnego, ale z własnym typem danych zamiast DateTimeOffset. Właśnie zaadaptowałem kod dla ciebie. Przechowuje datę jako czas UTC i offset jako TimeSpan (przechowuje Ticks Oczywiście nie potrzebujesz tej rozdzielczości, ale nie powinieneś przechowywać całych godzin dla stref czasowych, są tam przesunięcia stref czasowych z ułamkami godzin! ! I TimeSpan jest budowany w fabryce po wyjęciu z pudełka.)

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
public void SetPropertyValue(object component, int property, object value) 

Mam kod, który implementuje DateTime z dwóch pól int.

Kod zasadniczo jest właściwością przełączania (0 oznacza datę, 1 oznacza czas, w moim przypadku), a na końcu każdej instrukcji case obiekt komponentu jest ponownie przypisywany nowej instancji DateTime.

property = 0 (data):

// code to calculate year, month, day from object value 
DateTime dt = (DateTime)component; 
dt = new DateTime(year, month, day, dt.Hour, dt.Minute, dt.Second); 

property = 1 (czas):

// 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); 

Nie mam pojęcia, czy to jest dobry/zły, ale to działa na mnie (aka mam nie ma problemu z modyfikacją tego, do którego komponentu się odnoszą, do którego się odnawia, czy nie).

+0

Okej, dostatecznie ... Podążam do tej pory. Ale w jaki sposób twoja instancja 'dt' wraca do modelu domeny? – codekaizen

+0

dt = komponent, właśnie rzucony do DateTime. Mogę go zastąpić wszędzie z komponentem ((DateTime)). Składnik jest tym, co jest faktycznie oddawane z powrotem do modelu domeny. – anonymous

+0

Nie jestem pewien, czy istnieje dokumentacja tych rzeczy. Nawet o tym nie pamiętam i musiałem spojrzeć na kontekst w moim kodzie. Myślę, że musiałem spojrzeć na przykład zwykle dostarczany z NHibernate (jak sądzę?) I uczyć się na tym (i oczywiście zapomnieć o tym kiedy już skończyłem!) – anonymous

2

Rozumiem, że jeśli typ, z którym się mapujesz, a typ ICompositeUserType jest niezmienny, funkcja SetPropertyValue() nie powinna w ogóle nic robić, a nawet generować wyjątku, ponieważ nhibernate nie powinien wywoływać go.

Powiązane problemy