Benutzer mit den meisten Antworten
Linq to SQL: Mapping String -> Double

Frage
-
Hallo,
ich möchte in (A)Linq to SQL einen String auf Double mappen. Das funktioniert solange, wie keine Fehlerbehandlung erforderlich ist, sprich alle in der Spalte vorhandenen Werte sich problemlos in einen Double Wert parsen lassen.
private string _value; [ALinq.Mapping.Column(Storage = "_value")] public double value { get { return double.Parse(_value); } }
Soll jetzt auch ein Eintrag wie "+" oder "k.a." abgefangen und als Wert 0 geleifert werden, wird dies komplett ignoriert und es kommt eine FormatException, egal, ob vor der Umwandlung mittels RegEx geprüft wird, ich einen try/catch verwende oder explizit auf + oder k.a. prüfe.
Wo liegt mein Denkfehler?Grüße
Anja
Antworten
-
Hallo Anja,
Das Problem ist nicht ALinq-spezifisch, sondern hängt mit der Linq-Infrastruktur zusammen. Die FormatException ereignet sich zur Laufzeit, bei der Iteration über IQueryable<T>. Da der Ausnahmefehler schon bei der Materialisierung des jeweiligen Iterations-Objekts geworfen wird, lange vor dem Aufruf von [Entität].Value, bringt es auch nichts, die Umwandlungslogik in den Getter zu packen. Die Ausführung erreicht diesen Punkt nicht.
Wenn ich von der wahrscheinlich nicht möglichen datenbankseitigen Sanitisierung der Daten absehe, gäbe es noch folgende Möglichkeit:
[Column(Storage="_Value", DbType="NVarChar(50)", UpdateCheck=UpdateCheck.Never)] public string Value { get { return _Value; } } public double DoubleValue { get { double result = 0d; double.TryParse(this.Value, out result); return result; } }
Dabei verwendest Du einfach eine Wrapper-Property statt der originalen Property. Jetzt sollte auch die Iteration, bzw. die Materialisierung kein Problem mehr sein und Du erhältst trotzdem den gewünschten Wert zum Anzeigen:
var conn = @"Data Source=.;Initial Catalog=TestDb;Integrated Security=True"; var db = new ALinq.DataContext(new SqlConnection(conn), typeof(ALinq.SqlClient.Sql2005Provider)); var q = from s in db.GetTable<TestAnja>() select s; foreach (var t in q) Console.WriteLine(t.DoubleValue); Console.ReadKey(true);
Gruß
Marcel- Als Antwort markiert Anja Länge Montag, 18. Oktober 2010 18:37
-
Hallo Anja,
Du kannst zum Beispiel eine pragmatische Methode benutzen, die gleich typische "," / "." Problematiken mit abfängt.
In Deinem Beispiel würdest Du dann:return ToDouble(_value);
benutzen.
____________private void Form1_Load(object sender, EventArgs e) { string[] beispielStrings = new string[] { "+", "k.a.", "1.234", "1,234" }; foreach (var s in beispielStrings) { double dbl = ToDouble(s); MessageBox.Show(dbl.ToString()); } } /// <summary>Wandelt in String in Double um</summary> public static double ToDouble(string dblString) { double dblOut; if (Spezialfall(out dblOut, dblString)) return dblOut; dblString = dblString.Replace(",", "."); return double.Parse(dblString, CultureInfo.InvariantCulture); } private static bool Spezialfall(out double dbl, string dblString) { if (dblString.Trim() == "+") {dbl = 0; return true;} if (dblString.Trim() == "k.a.") {dbl = 0; return true;} dbl = 0; return false; } /// <summary>Wandelt String in double um, /// gibt 'standardWert' zurück, falls es nicht möglich ist. /// </summary> public static double ToDouble(string dblString, double standardWert) { double dblOut; if (Spezialfall(out dblOut, dblString)) return dblOut; dblString = dblString.Replace(",", "."); try { dblOut = double.Parse(dblString, CultureInfo.InvariantCulture); } catch { dblOut = standardWert; } return dblOut; } /// <summary> /// Wandelt einen String in Double um (Default = 0 /// oder es wird eine Exception ausgelöst) /// </summary> public static double ToDouble(string dblString, bool ausnahmeWerfen) { double dblOut; if (Spezialfall(out dblOut, dblString)) return dblOut; dblString = dblString.Replace(",", "."); try { dblOut = double.Parse(dblString, CultureInfo.InvariantCulture); } catch (Exception ex) { if (ausnahmeWerfen) throw ex; else dblOut = 0; } return dblOut; }
ciao Frank- Als Antwort markiert Robert BreitenhoferModerator Mittwoch, 6. Oktober 2010 13:21
Alle Antworten
-
Hallo Anja,
Du kannst zum Beispiel eine pragmatische Methode benutzen, die gleich typische "," / "." Problematiken mit abfängt.
In Deinem Beispiel würdest Du dann:return ToDouble(_value);
benutzen.
____________private void Form1_Load(object sender, EventArgs e) { string[] beispielStrings = new string[] { "+", "k.a.", "1.234", "1,234" }; foreach (var s in beispielStrings) { double dbl = ToDouble(s); MessageBox.Show(dbl.ToString()); } } /// <summary>Wandelt in String in Double um</summary> public static double ToDouble(string dblString) { double dblOut; if (Spezialfall(out dblOut, dblString)) return dblOut; dblString = dblString.Replace(",", "."); return double.Parse(dblString, CultureInfo.InvariantCulture); } private static bool Spezialfall(out double dbl, string dblString) { if (dblString.Trim() == "+") {dbl = 0; return true;} if (dblString.Trim() == "k.a.") {dbl = 0; return true;} dbl = 0; return false; } /// <summary>Wandelt String in double um, /// gibt 'standardWert' zurück, falls es nicht möglich ist. /// </summary> public static double ToDouble(string dblString, double standardWert) { double dblOut; if (Spezialfall(out dblOut, dblString)) return dblOut; dblString = dblString.Replace(",", "."); try { dblOut = double.Parse(dblString, CultureInfo.InvariantCulture); } catch { dblOut = standardWert; } return dblOut; } /// <summary> /// Wandelt einen String in Double um (Default = 0 /// oder es wird eine Exception ausgelöst) /// </summary> public static double ToDouble(string dblString, bool ausnahmeWerfen) { double dblOut; if (Spezialfall(out dblOut, dblString)) return dblOut; dblString = dblString.Replace(",", "."); try { dblOut = double.Parse(dblString, CultureInfo.InvariantCulture); } catch (Exception ex) { if (ausnahmeWerfen) throw ex; else dblOut = 0; } return dblOut; }
ciao Frank- Als Antwort markiert Robert BreitenhoferModerator Mittwoch, 6. Oktober 2010 13:21
-
Hallo,
das funktioneirt in einem normalen Programmablauf, aber leider nicht, wenn der Double-Wert eine Eigenschaft eines Objektes ist, das ich mittels ALinq aus einer DB erstelle. Wie bei meinen anderen Versuchen vorher, bei denen ich ja auch bereits die Sonderfälle berücksichtigt hatte, läuft dann die FormatException auf. Ist das ein Problem speziell von ALinq oder generell in den Linq to xy Lösungen?
Grüße
Anja -
Hallo Anja,
Das Problem ist nicht ALinq-spezifisch, sondern hängt mit der Linq-Infrastruktur zusammen. Die FormatException ereignet sich zur Laufzeit, bei der Iteration über IQueryable<T>. Da der Ausnahmefehler schon bei der Materialisierung des jeweiligen Iterations-Objekts geworfen wird, lange vor dem Aufruf von [Entität].Value, bringt es auch nichts, die Umwandlungslogik in den Getter zu packen. Die Ausführung erreicht diesen Punkt nicht.
Wenn ich von der wahrscheinlich nicht möglichen datenbankseitigen Sanitisierung der Daten absehe, gäbe es noch folgende Möglichkeit:
[Column(Storage="_Value", DbType="NVarChar(50)", UpdateCheck=UpdateCheck.Never)] public string Value { get { return _Value; } } public double DoubleValue { get { double result = 0d; double.TryParse(this.Value, out result); return result; } }
Dabei verwendest Du einfach eine Wrapper-Property statt der originalen Property. Jetzt sollte auch die Iteration, bzw. die Materialisierung kein Problem mehr sein und Du erhältst trotzdem den gewünschten Wert zum Anzeigen:
var conn = @"Data Source=.;Initial Catalog=TestDb;Integrated Security=True"; var db = new ALinq.DataContext(new SqlConnection(conn), typeof(ALinq.SqlClient.Sql2005Provider)); var q = from s in db.GetTable<TestAnja>() select s; foreach (var t in q) Console.WriteLine(t.DoubleValue); Console.ReadKey(true);
Gruß
Marcel- Als Antwort markiert Anja Länge Montag, 18. Oktober 2010 18:37