2011-07-07 9 views
6

Mam tabela sql z kolumną ciąg znaków, która może zawierać pusty, pusty ciąg lub podwójną wartość. Chcę odwzorować tę kolumnę na właściwość C#, która jest double, domyślnie ustawiona na zero, gdy kolumna jest pusta lub pusta. Czy mogę to zrobić z mapowaniem fluent-nhibernate? Próbowałem to:Konwertowanie ciągu na podwójne w mapowaniu fluent-nhibernate

Map(p => p.doubleProperty).CustomSqlType("varchar(20)").CustomType("double").Default("0"); 

i wariacje na ten temat, ale zawsze pojawia się błąd, że konwersja nie powiodła się.

Odpowiedz

1

Po prostu zamapowałbym to na ciąg znaków, a w twoim podmiocie ma właściwość podwójną, która dokonuje konwersji. Wydaje się łatwiejsze i czystsze niż robienie tego w mapowaniu.

Może coś takiego:

public double Price 
{ 
    get 
    { 
     double price = -1.0; 
     Double.TryParse(stringProperty, out price); 
     return price; 
    } 
    set { stringProperty = value.ToString(); } 
} 
+0

Nie jestem więc pewien, że to czystsze, że muszę mieć właściwości String dla NH używać podczas zapisywania i podwójne nieruchomość do wykorzystania podczas dostępu do niego z kodu. Tak, jeśli rozumiem, co sugerujesz poprawnie. Jeśli mam tylko jedną podwójną właściwość, NH zapisuje ją jako podwójną, a nie jako ciąg. – Mike

+0

touch ... Chciałem wziąć czystszą część. Czystsze, jeśli chodzi o twoje mapowanie, ale nie twoje ciało. W tym rozwiązaniu miałbyś prywatną zmienną łańcuchową i publiczną podwójną właściwość. –

5

Na razie Poszedłem z niestandardowego typu, które pozwala mi korzystać

 Map(p=>p.doubleProperty).CustomType<DoubleString>(); 

Co zrobi dla moich potrzeb.

Zostawię pytanie otwarte na razie na wypadek, gdyby ktoś wymyślił łatwiejsze rozwiązanie.

Kod typu DoubleString znajduje się poniżej.

public class DoubleString : IUserType 
{ 
    public new bool Equals(object x, object y) 
    { 
     if (ReferenceEquals(x, y)) 
     { 
      return true; 
     } 
     if (x == null || y == null) 
     { 
      return false; 
     } 
     return x.Equals(y); 
    } 

    public int GetHashCode(object x) 
    { 
     return x.GetHashCode(); 
    } 

    public object NullSafeGet(IDataReader rs, string[] names, object owner) 
    { 
     var valueToGet = NHibernateUtil.String.NullSafeGet(rs, names[0]) as string; 
     double returnValue = 0.0; 
     double.TryParse(valueToGet, out returnValue); 
     return returnValue; 
    } 

    public void NullSafeSet(IDbCommand cmd, object value, int index) 
    { 
     object valueToSet = ((double)value).ToString(); 
     NHibernateUtil.String.NullSafeSet(cmd, valueToSet, 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 DeepCopy(cached); 
    } 

    public object Disassemble(object value) 
    { 
     return DeepCopy(value); 
    } 

    public SqlType[] SqlTypes 
    { 
     get 
     { 
      return new[] { new SqlType(DbType.String) }; 
     } 
    } 

    public Type ReturnedType 
    { 
     get { return typeof(double); } 
    } 

    public bool IsMutable 
    { 
     get { return true; } 
    } 
} 
+0

Świetnie, to rozwiązało przypadek, w którym musiałem utrzymywać niestandardową 'struct' jako ciąg znaków w bazie danych! Byłbym bardzo wdzięczny, gdybyś miał jakieś wskazówki, jak zmodyfikować powyższe, aby działał z 'Nullable ' typami. Czy trzeba go zmienić, aby działał z nullablem, czy też muszę grać tylko z konwencją typu użytkownika? –

+1

To bardzo fajna odpowiedź. W moim przypadku musiałem zmienić 'ToString()' na linii 40 na: '.ToString (System.Globalization.CultureInfo.GetCultureInfo (" en-US "));' ponieważ 'ToString()' zmienia podwójne z, np '1,23' do' 1,23', a SQL go nie zaakceptował. W kulturze zachowuje kropkę zamiast przecinka. – DontVoteMeDown

0

Rozwiązałem rodzaj tego samego problemu, używając dwóch właściwości, które odnosiły się do tej samej zmiennej prywatnej. W moim przykładzie baza danych zawiera varchar, który NIE jest UŻYWANY ani RZECZYWISTY, w związku z czym chciałem mieć Bool w mojej aplikacji.

private bool _myBool= true; 

    public virtual bool MyBool{ get { return _myBool; } set { _myBool= value; } } 

    public virtual string MyString 
    { 
     get { return _myBool ? "ACTUAL" : "NOT USED"; } 
     set { _myBool= value.Equals("NOT USED"); } 
    } 
} 
Powiązane problemy