Montag, 16. April 2012

Umzug...

Habe lange nichts geschrieben, da ich derzeit zu Hause umbaue und in Kürze mit meiner Familie die frisch renovierte Wohnung beziehen werde. Voraussichtlich irgendwann mitte Mai.


Donnerstag, 5. April 2012

Der sagenumwobene Viewstate

Seit ich mich im .Net Umfeld bewege, konnte ich die Sache mit diesem "Viewstate" nicht wirklich nachvollziehen. Seit vor einiger zeit das Problem aufkam, dass in einem unserer Produkte ein speichervorgang einer Seite mehrere Minuten dauern konnte, bin ich dem Problem auf den Grund gegangen und habe festgestellt, dass der Viewstate auf über 6MiB angewachsen war.
Die Seite als solches ist dabei aber recht einfach gestrickt und besteht im Grunde aus einer Tabelle mit 5 Spalten von Dropdownboxen, aus der eine Auswahl getroffen werden kann. Klar kommt da schnell eine Menge an Daten zusammen, zumal eine der Auswahlmöglichkeiten mehr als 100 Textbausteine enthalten kann.

Die Große Frage aber, die sich mir stellt: Warum so ein riesiger Viewstate für ein paar Dropdownboxen? Dieses nachverfolgt, stellt sich heraus, dass X-Mal der identische Inhalt der Textbausteine im Viewstate vorgehalten wird.
Zur Lösung des Problems habe ich ein Control in der Form einer Textbox erstellt, die beim "Lostippen" vorschläge zur Auswahl stellt, in denen der gesuchte Begriff vorkommt. Anschließend habe ich den ViewState für den Dialog abgeschaltet und der Performance-Gewinn war unbestreitbar.

ViewState? Wozu?

Hilfreich zu diesem Thema ist auch der folgende Artikel aus dem MSDN: "Ein mundgerechtes Stück ASP.NET ViewState"

ViewState die Zweite...

Man nehme ein Grid und deaktiviere den ViewState für dieses, da das bekannte Anwachsen des Selbigen immer wieder zu Performance-Problemem führt, insbesondere wenn die Anwendung über eine schwachbrüstige Internetleitung aufgerufen wird.
Führt man nun über ein weiteres Steuerelement der Seite eine Aktion aus, die einen Postback mit sich bringt, wird das Grid neu an die Datenquelle gebunden und zuvor gemachte Eingaben sind verloren. Also doch der ViewState? Nein, lieber nicht. Um dieses Problem (was eigentlich keines ist) zu umschiffen habe ich folgende Klasse erstellt, welche vorhandene, aber nicht gespeicherte Angaben des Grids in der entsprechenden Datenquelle, dem DataView vornimmt, ganz ohne Viewstate.

Public Class UpdateView
        Private _grid As RadGrid
        Private _assignments As SortedDictionary(Of String, String) = New SortedDictionary(Of String, String)
        Public Property Assignments As SortedDictionary(Of String, String)
            Get
                Return _assignments
            End Get
            Set(value As SortedDictionary(Of String, String))
                _assignments = value
            End Set
        End Property

        Public ReadOnly Property Grid As RadGrid
            Get
                Return _grid
            End Get
        End Property

        Public Sub New(ByVal grid As RadGrid)
            Me._grid = grid
        End Sub

        Public Sub Update(ByRef dataView As DataView)
            Dim oldCulture As System.Globalization.CultureInfo = dataView.Table.Locale
            dataView.Table.Locale = New System.Globalization.CultureInfo("en-US")
            'sonstige Änderungen übernehmen ohne MegaByte Weise Viewstate für's RadGrid
            For Each p As String In HttpContext.Current.Request.Params                                               'Request Parameter itereieren
                If p.Contains(_grid.UniqueID) Then                                                                   'prüfen ob der der aktuelle Eintrag zum RadGrid gehört
                    Dim a = _grid.FindControl(p.Replace(_grid.UniqueID & "$", ""))                                   'das entsprechende Steuerelement finden
                    If a IsNot Nothing Then
                        If Assignments.Keys.Contains(a.ID) Then                                                      'prüfen ob das Steuerelement zu aktualisieren ist
                            Dim row = CType(a.Parent.NamingContainer, GridDataItem).ItemIndex                        'entsprechende Row des RadGrids ermitteln
                            dataView.Table.Rows(row).Item(Assignments(a.ID)) = HttpContext.Current.Request.Params(p) 'DataView-Feld mit dem entsprechenden Datum aktualisieren
                        End If
                    End If
                End If
            Next
            'Ende
            dataView.Table.Locale = oldCulture
        End Sub
    End Class

Anschließend kann man je nach Belieben bestimmte Werte im Grid, bzw. der dazugehörigen DataView aktualisieren, sodass beim Laden die Datenbindung an eine aktualisierte View erfolgt.
Warum ich in obigem Beispiel die Culture der DataView auf "en-US" setze und später wieder auf die eigentliche Kultur, erklärt sich im Artikel "CultureInfo: Chaos im .Net"

Beispiel:
Dim updateView As LCT.Tools.UpdateView = New LCT.Tools.UpdateView(RadGrid)
        updateView.Assignments.Add("GridEditItemID1", "DataViewColumnName1")
        updateView.Assignments.Add("GridEditItemID2", "DataViewColumnName2")
        updateView.Update(DataView)
So far...

Mittwoch, 4. April 2012

Raspberry Pi

Habe soeben bei Farnell einen Raspberry Pi bestellt! Freue mich auf das tolle Spielzeug!


Sobald es da ist, werde ich mal schauen ob ich es als PDC für's Heimnetzwerk konfiguriert bekomme und teste was sonst noch mit der Kiste möglich ist.

Weitere Info über den Mini-Computer: http://www.raspberrypi.org/

Dienstag, 3. April 2012

CultureInfo: Chaos im .Net

eine Dataview in einer ASP-Seite, die mit der Culture-Info "de-DE" initialisiert wird, verhält sich äußerst eigenartig, wenn man hier versucht einen "Double" wert in der View abzulegen, der beispielsweise über Post-Parameter (demzufolge als String) an das Script übergeben wird.

VB Beispiel:
            dataView.Table.Columns(x).DataType = GetType(Double)
            dataView.Table.Rows(n).Item(x) = "45.2"

            Console.WriteLine(dataView.Table.Rows(n).Item(x))
 // Ausgabe: 452.0

Ebenso wird ein Cast von String nach Double in der Kultur "de-DE" m.E. falsch übersetzt, aus:

            CDbl("41.5")

wird 415.0

Wow! Das klappt ja prima! Da bekommt man ein Double im String Format und wegen einer Culture-Einstellung wird diese missinterpretiert. Also wirklich, meine lieben Damen und Herren von Microsoft. Der Datentyp der Spalte ist Double und nur weil die CultureInfo auf "de-DE" steht wird ein ","(Komma) als Dezimaltrennzeichen angenommen. Solche formate grundsätzlich auf die angegebene Kultur anzuwenden ist zwar konsequent, allerdings aus meiner Sicht nicht praktikabel, da man als Entwickler von mehrsprachigen Anwendungen hier zusätlich noch beim Konvertieren von Werten auf die Ländereinstellung achten muss.

Seit ich programmiere sind double Werte mit einem .(Punkt) als Dezimaltrennzeichen versehen, warum wird im .Net davon abgewichen? Damit die Fehleranfälligkeit erhöht wird?

Eine ganz ähnliche Problematik ergibt sich zum Beispiel bei Datumswerten unter anderem im SQL-Server. Ich frage mich wirklich, warum sowas sein muss? Reicht es nicht sich programmatisch auf EIN EINZIGES Format (zum Beispiel das US-englische) zu beschränken und lediglich bei der Ausgabe/Anzeige der Werte in der Oberfläche eine entsprechende Konvertierung vorzunehmen?