Autor Beitrag
Oppi35
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 95
Erhaltene Danke: 3



BeitragVerfasst: Di 28.06.11 22:46 
Hallo Zusammen,

zu folg. Code ist folg. zu erwähnen:

Die Spalte "Monatsbeitrag" beinhaltet string-Werte. Dezimaltrenner ist das Komma (sofern man bei strings davon sprechen kann:))
Hier handelt es sich nur um eine Testanwendung. Dieses Problem habe ich eigentlich bei einer größeren DataTable, bei der ich die Daten aus einer CSV-Datei einlese.

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
DataTable dt = new DataTable();
            dt.Columns.Add("Name");
            dt.Columns.Add("Monatsbeitrag");

            List<DataRow> rows = new List<DataRow>();
            for (int i = 0; i < 5; i++)
            {
                DataRow row = dt.NewRow();
                rows.Add(row);
            }

            rows[0]["Name"] = "Meier";
            rows[0]["Monatsbeitrag"] = "23,47";

            rows[1]["Name"] = "Schmidt";
            rows[1]["Monatsbeitrag"] = "33,47";

            rows[2]["Name"] = "Meier";
            rows[2]["Monatsbeitrag"] = "43,47";

            rows[3]["Name"] = "Meier";
            rows[3]["Monatsbeitrag"] = "53,47";

            foreach (DataRow row in rows)
            {
                dt.Rows.Add(row);                
            }

var query = from c in dt.AsEnumerable()
                        group c by new
                        {
                            c1 = c["Name"]
                        } into grp
                        select new
                        {
                            NameNeu=grp.Key.c1,
                            Jahresbeitrag = grp.Sum (r=>Convert.ToDecimal( r["Monatsbeitrag"]))
                        };

foreach (var item in query)
            {
                Console.WriteLine(item.Jahresbeitrag.ToString());
            }

            Console.Read();


Mein Problem ist jetzt die Invalid Cast Exception: "Ein Objekt kann nicht von DBNull in andere Typen umgewandelt werden."

Die Ursache ist, dass in der Schleife 3 neue Rows angelegt werden, die vierte aber Null ist. Wie kann die Summierung auch mit Null-Werten sauber durchgeführt werden?

Gruß
Frank
norman2306
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 222
Erhaltene Danke: 16

Win XP, Win 7 64-Bit
C# 4.0 (VS2010)
BeitragVerfasst: Mi 29.06.11 08:25 
Um deine Frage exakt zu beantworten. Ersetze mal die Zeile

ausblenden C#-Quelltext
1:
Jahresbeitrag = grp.Sum (r=>Convert.ToDecimal( r["Monatsbeitrag"]))					


durch

ausblenden C#-Quelltext
1:
Jahresbeitrag = grp.Sum (r => Convert.ToDecimal(r["Monatsbeitrag"] == DBNull.Value ? 0 : r["Monatsbeitrag"]))					


Alternativ kannst du in deinem 'query' eine 'where'-Klausel einfügen:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
            var query = from c in dt.AsEnumerable()
                        where !(c.IsNull("Name") || c.IsNull("Monatsbeitrag"))
                        group c by new
                        {
                            c1 = c["Name"]
                        } into grp
                        select new
                        {
                            NameNeu = grp.Key.c1,
                            Jahresbeitrag = grp.Sum(r => Convert.ToDecimal(r["Monatsbeitrag"]))
                        };


Dadurch werden Null-Einträge ganz ausgeschlossen, was wohl dem eigentlichen Zweck besser dient.

Noch besser wird es, wenn du deinen Convert-Ausdruck durch ein Parse ersetzt:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
            decimal dummy;
            var query = from c in dt.AsEnumerable()
                        where !(c.IsNull("Name") || c.IsNull("Monatsbeitrag") || decimal.TryParse((string)c["Monatsbeitrag"], out dummy))
                        group c by new
                        {
                            c1 = c["Name"]
                        } into grp
                        select new
                        {
                            NameNeu = grp.Key.c1,
                            Jahresbeitrag = grp.Sum(r => decimal.Parse((string)r["Monatsbeitrag"]))
                        };

Für diesen Beitrag haben gedankt: Oppi35
Oppi35 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 95
Erhaltene Danke: 3



BeitragVerfasst: Mi 29.06.11 16:38 
Hallo Norman,

vielen Dank für Deine Hilfe.

Die folg. Zeile funktioniert nach einem ersten Test super.
ausblenden C#-Quelltext
1:
Jahresbeitrag = grp.Sum (r => Convert.ToDecimal(r["Monatsbeitrag"] == DBNull.Value ? 0 : r["Monatsbeitrag"]))					

Die Variante mit der Where-Klausel ist allerdings für mich nicht optimal.

Grund:
Wenn ich eine zweite Spalte habe, die ich zusätzlich summieren möchte, erhalte ich falsche Werte. Denn es werden ja mit der Where-Klausel schonmal alle Datensätze rausgefiltert, bei denen das Feld "Moantsbeitrag" == null ist; obwohl ein weiteres zu summierendes Feld event. Werte enthält.

Auf mein gegebenes Beispiel ist es aber natürlich so auch richtig.

Kannst Du mir den Teil hinter dem Gleichheitszeichen noch erläutern? "DBNull.Value ? 0 : r["Monatsbeitrag"]))"

Insbesondere die Syntax mit "? 0 :r" kenne ich leider nicht und konnte ich auch in keinem meiner Bücher finden.

Gruß
Frank

Moderiert von user profile iconTh69: C#-Tags hinzugefügt
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4799
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mi 29.06.11 16:55 
Hallo Frank,

s. Operator ?:

Für diesen Beitrag haben gedankt: Oppi35