2012-10-01 2 views
6

ich dieses Problem habe, ich habe eine Tabelle für EinkäufeConvert String in einem Entity Framework Linq-Abfrage in int und die Parsing Ausnahmebehandlung

Purchases(Date DateTime, Number string) 

ich will, ist ein neuer Rekord zu schaffen, so brauche ich der Max (Number), das Problem ist hier, dass Nummer ein String ist, ich habe versucht

Purchases.Select(X=>int.Parse(X.Number)).Max() 

aber es könnte eine Ausnahme werfen, habe ich so eine benutzerdefinierten ToInt() Erweiterung erstellen, wenn ich

Purchases.Select(X=>X.Number.ToInt()).Max() 

es löst eine Ausnahme, dass mein ToInt() kann nicht mit Linq-Abfrage gleiche wie die berühmte ToString()

so meine Frage verwendet werden: Gibt es einen Weg, um eine Zeichenfolge zu werfen zu int in linq Abfrage & Behandlung von Ausnahmen zur gleichen Zeit oder um benutzerdefinierte Funktionen zu einer Linq-Abfrage zu integrieren!

und dies ist meine Erweiterung

public static int ToInt(this string s) 
    { 
     try 
     { 
      return int.Parse(s); 
     } 
     catch 
     { 
     } 
     return 0; 
    } 
+4

Gibt es einen Grund dafür, dass das Feld "Number" in Ihrer Tabelle als "String" deklariert ist? –

+0

Können wir die von Ihnen erstellte Erweiterung sehen? –

+0

Wie behandeln Sie, wenn eine Ausnahme ausgelöst wird? fährt fort zu summieren oder zu stoppen? –

Antwort

10

Erster Weg:

var numbers = Purchases.Select(x => x.Number).ToList(); 

int temp; 
int max = numbers.Select(n => int.TryParse(n, out temp) ? temp : 0).Max(); 

Console.WriteLine("Max: {0}", max); 

Zweiter Weg:

int temp2; 
int max2 = Purchases.Select(x => x.Number).ToList().Select(n => int.TryParse(n, out temp2) ? temp2 : 0).Max(); 

Console.WriteLine("Max 2: {0}", max2); 

Der Schlüssel ist die .ToList() in diesen beiden Möglichkeiten. Es ruft alle string Daten aus der Datenbank ab. Wenn Sie also int.TryParse für die Ergebnisse aufrufen, wurde die Datenbankabfrage bereits ausgeführt. Daher wird reiner CLR-Code verwendet und nicht versucht, int.TryParse in eine SQL-Abfrage zu konvertieren. Ich habe einen EF-Kontext in einem meiner Sandbox-Projekte erstellt und bestätigt, dass das funktioniert.

+1

sollten Sie immer 'DefaultIfEmpty' hinzufügen wir wollen keine weitere Ausnahme sehen – S3ddi9

+0

' int.TryParse' wird keine Ausnahme auslösen. Das ternary gibt Ihnen den Standardwert, wenn 'int.TryParse'' false' zurückgibt, was bedeutet, dass die Konvertierung fehlgeschlagen ist. – Gromer

+0

Sie können auch Varianten dieser Abfragen verwenden, um herauszufinden, welche nicht konvertiert werden. 'int temp3; var noConvert = Purchases.Select (x => x.Number) .ToList() .Wobei (n => int.TryParse (n, out temp3) == false); ' – Gromer

2

Ich verstehe nicht, warum Sie die Ausnahme nicht wollen, denn wenn man das Gießen fehlgeschlagen ist, dann bedeutet es, etwas falsch zu Ihrer Anwendung passiert ist (oder zumindest, also ich bekomme es). Ich verstehe auch nicht, warum ich eine Nummer als String in der Datenbank speichern soll. Normalerweise behältst du es als Nummer, damit du später nicht mit Problemen wie dieser umgehen musst. Wenn jemand versucht, einen falschen Wert einzufügen, scheitert die Eingabe.

ABER - wenn Sie möchten, dass diese Linie funktioniert, sollten Sie int.TryParse verwenden, die Ihnen wahr zurückgibt, wenn der Wert erfolgreich gegossen wird und den Wert in 'out' Mitglied, die aus der Abfrage sein wird. wie folgt:

int tmp; 
Purchases.Select(X=>int.TryParse(X.Number, out tmp) ? tmp : 0).Max() 

und statt "0" einen Standardwert eingeben, der nicht mit Ihrer Logik verwechselt wird.

+0

das ist sehr schlau sehr sehr nette Antwort !!! – S3ddi9

+4

Sie können 'int.TryParse' nicht in einer _EF_ Abfrage verwenden. Sie erhalten dies: 'Nicht behandelte Ausnahme: System.NotSupportedException: LINQ to Entities erkennt die Methode 'Boolean TryParse (System.String, Int32 ByRef)' 'Methode nicht, und diese Methode kann nicht in einen Ausdruck übersetzt werden.' – Gromer

+0

ja das ist rechts – S3ddi9