DevExpress XPO: Teure SQL-Abfrage beim Aufruf von XPCollection.EndInit()

Für Projekte in .NET verwende ich sehr gerne die Steuerelemente von DevExpress (Englisch). Darüber hinaus ist DevExpress XPO als Datenbank-Abstraktionsebene sehr nützlich.

Jedoch stieß ich in einem aktuellen Projekt auf ein sehr seltsames Problem:

Bei einigen Formularen (seltsamerweise nicht bei allen) wurde eine sehr teure SQL-Abfrage an das Datenbank-Backend gesendet während das Formular geladen wurde. Es war im Prinzip eine SQL-Abfrage, die sämtliche (und ich meine wirklich alle) Datenzeilen von der Datenbank lud, was offensichtlich keine besonders gute Idee ist. Aber wie geschrieben war das nicht für alle Formulare der Fall: Bei den anderen Formularen wurde erwartungsgemäß nur das aktuelle Datenobjekt (die aktuelle Zeile der Tabelle) geladen.

Natürlich kontaktierte ich zunächst den immer sehr schnellen und hilfreichen DevExpress-Support. Sie haben untersucht, was die Datenabfrage auslöst und festgestellt, dass die Eigenschaft XPCollection.Count von dem CurrencyManager nach dem Methodenaufruf Control.UpdateBindings angefordert wird. Da dies etwas innerhalb des .NET Frameworks ist, konnten sie daran leider nichts ändern.

Sie schlugen vor die XPCollection nicht zur Design-Zeit zu setzen. Dies hätte jedoch bedeutet, dass ich die Formulare nicht mehr mit dem Windows-Formular-Designer erstellen könnte. Das wäre ganz schlecht, da ich viele große Formular in diesem Projekt habe, die ich sicherlich nicht alle im Quelltext erstellen möchte.

Ich fand jedoch einen andere Weg – ich nenne das nicht eine Lösung, nur ein Work-Around –, um den Designer weiterhin verwenden zu können:

Hierzu habe ich einfach zwei Batch-Dateien (unter Verwendung des Kommandozeilen-Ersetzungstools namens FART (Englisch)) geschrieben: Eine, die ausgeführt wird bevor das Build beginnt und sicherstellt, dass keine XPCollection innerhalb der Methode InitializeComponent initialisiert wird (und dabei einfach die Quelltextzeilen auskommentiert), und eine zweite, die nach dem Build läuft und die Änderungen wieder rückgängig macht.

Hier ist der Inhalt der Pre-Build-Batch-Datei:

%1Tools\fart.exe -r -C "%1*.designer.cs" "this.xpKern = new DevExpress.Xpo.XPCollection(this.components);" "\x2f\x2fthis.xpKern = new DevExpress.Xpo.XPCollection(this.components);"
%1Tools\fart.exe -r -C "%1*.designer.cs" "((System.ComponentModel.ISupportInitialize)(this.xpKern)).BeginInit();" "\x2f\x2f((System.ComponentModel.ISupportInitialize)(this.xpKern)).BeginInit();"
%1Tools\fart.exe -r -C "%1*.designer.cs" "this.xpKern.ObjectType = typeof(Administration.Daten.Kern);" "\x2f\x2fthis.xpKern.ObjectType = typeof(Administration.Daten.Kern);"
%1Tools\fart.exe -r -C "%1*.designer.cs" "this.xpKern.Session = this.unitOfWork;" "\x2f\x2fthis.xpKern.Session = this.unitOfWork;"
%1Tools\fart.exe -r -C "%1*.designer.cs" "((System.ComponentModel.ISupportInitialize)(this.xpKern)).EndInit();" "\x2f\x2f((System.ComponentModel.ISupportInitialize)(this.xpKern)).EndInit();"

@exit 0

Und die Post-Build-Datei, welche die Änderungen wieder rückgängig macht:

%1Tools\fart.exe -r -C "%1*.designer.cs" "\x2f\x2fthis.xpKern = new DevExpress.Xpo.XPCollection(this.components);" "this.xpKern = new DevExpress.Xpo.XPCollection(this.components);"
%1Tools\fart.exe -r -C "%1*.designer.cs" "\x2f\x2f((System.ComponentModel.ISupportInitialize)(this.xpKern)).BeginInit();" "((System.ComponentModel.ISupportInitialize)(this.xpKern)).BeginInit();"
%1Tools\fart.exe -r -C "%1*.designer.cs" "\x2f\x2fthis.xpKern.ObjectType = typeof(Administration.Daten.Kern);" "this.xpKern.ObjectType = typeof(Administration.Daten.Kern);"
%1Tools\fart.exe -r -C "%1*.designer.cs" "\x2f\x2fthis.xpKern.Session = this.unitOfWork;" "this.xpKern.Session = this.unitOfWork;"
%1Tools\fart.exe -r -C "%1*.designer.cs" "\x2f\x2f((System.ComponentModel.ISupportInitialize)(this.xpKern)).EndInit();" "((System.ComponentModel.ISupportInitialize)(this.xpKern)).EndInit();"

@exit 0

Das @exit 0 am Ende dieser ist wichtig, da ansonsten ein Code 2 zurückgegeben wird (warum auch immer) und das Visual-Studio-Build-System sich bei jedem Build darüber beschwert.

Nun müssen Sie nur doch diese Batch-Dateien in den Visual-Studio-Buildereignissen mit

$(ProjectDir)Tools\PreBuild.bat $(ProjectDir)

beziehungsweise

$(ProjectDir)Tools\PostBuild.bat $(ProjectDir)

aufrufen.

Ich weiß, dass dies keine besonders gute “Lösung” ist, aber das war die einzige Idee, die ich hatte, dass ich weiterhin den Formular-Designer verwenden kann und trotzdem diese teuren SQL-Anfragen vermeide.

Hatten Sie bereits einmal dieses Problem und vielleicht sogar eine bessere Lösung dafür? Ich freue mich über jeden anderen Vorschlag zu diesem Thema!

Intel Ultrabook MeetUp in München

Heute war ein zweiter Intel Ultrabook MeetUp in München dieses Jahr. Der erste war im Juli.

Intel Ultrabook MeetUp in München

Ich war eingeladen dort ein bisschen was zu meiner Erfahrung hinsichtlich der Migration einer HTML5-App zum Modern Style UI (ürsprünglich Metro) von Windows 8 zu erzählen. Hierbei habe ich als Beispiel mein Vokabel-Trainer-Projekt verwendet.

Developer Open Space in Leipzig

Dieses Wochenende finde die alljährliche Developer Open Space (vormals .NET Open Space) in Leipzig mit rund 150 Teilnehmern statt.

Developer Open Space 2012

Ich wurde eingeladen dort heuten einen Vortrag über die Nutzung der neuesten Intel Ultrabook Features unter Windows 8 zu halten. Hierbei habe ich als Beispiel mein Vokabel-Trainer-Projekt verwendet.

Developer Open Space 2012: Nach Vortrag

Nach dem Vortrag nutzen einige Teilnehmer die Möglichkeit einen genaueren Blick auf das neue Intel Ultrabook zu werfen und Fragen zur Anwendungsentwicklung unter Windows 8 zu stellen.

Waren auch Sie bei der Developer Open Space?

Ultimate Coder Challenge: Hinzufügen eines Wörter-Kartenspiels

Nach einigen Interface-Verbesserungen in meinem letzten Artikel, fügte ich in der Zwischenzeit ein Wörter-Kartenspiel zu der Vokabel-Trainer-App hinzu.

Aber zunächst erweiterte ich die Hauptansicht mit einem Semantic Zoom. So sieht die normale Ansicht aus:

Screenshot des Vokabel-Trainers: Ohne Semantic Zoom

Und mit Semantic Zoom (herausgezoomt):

Screenshot des Vokabel-Trainers: Mit Semantic Zoom

Falls viele Lektionen dargestellt werden sollen, bekommt der Benutzer auf diese Weise eine bessere Übersicht.

Aber nun zum interessanteren Teil: Das Wörter-Kartenspiel, welches ähnlich wie das Spiel Memory® von Ravensburger aussieht:

Es zeigt zunächst zugedeckte Spielkarten an. Nachdem der Benutzer eine Karte berührt bzw. darauf geklickt hat, wird diese aufgedeckt und ein Wort in einer der beiden Sprachen der aktuellen Lektion angezeigt. Der Benutzer muss dann das dazu passende übersetzte Wort finden.

Sollten zu viele Wörter in einer Lektion sein, um alle anzuzeigen, werden die Wörter automatisch zufällig ausgewählt.

Hier sieht man, wie es nun aussieht:

Screenshot des Vokabel-Trainers: Wörter-Kartenspiel

OK, das war der letzte Artikel in der Ultimate Coder Challenge von mir.

Natürlich gäbe es noch genug Ideen, was man dem Vokabel-Trainer hinzufügen könnte – vor allem die Online-Sychronisation sollte bald verfügbar sein –, aber in diesem Wettbewerb ist keine Zeit mehr dafür.

Zusammenfassend kann man sagen, dass es möglich ist eine HTML5-App in sechs Wochen in das neue Windows 8 UI Design zu überführen, aber es ist wirklich viel Arbeit. Auch, wenn Microsoft sagt, dass man mit HTML5 nur einmal entwickelt und danach auf verschiedenen Platformen veröffentlichen kann, so ist dies doch mehr eine Wunschvorstellung. In der Praxis muss man eine ganze Menge an Extra-Arbeit leisten, um das richtige Look & Feel für jede Platform zu bekommen – besonders für Windows 8.

Aber ich hoffe, Ihnen hat das Lesen meiner Artikel Spaß gemacht!

Ultimate Coder Challenge: IDF und Interface-Verbesserungen

Es hat mich sehr gefreut letzte Woche wieder zur IDF in San Francisco eingeladen worden zu sein.

Dort durfte ich meinen Vokabel-Trainer an einem Stand von Intel im Bereich des technischen Showcases vorstellen.

IDF 2012: Showcase

Aber ich hatte auch Zeit, um einige Interface-Verbesserungen für den Vokabel-Trainer umzusetzen.

Zunächst habe ich die Wörterbuchansicht optimiert:

Screenshot des Vokabel-Trainers: Wörterbuch bearbeiten

Es gibt keinen Grund die Flaggen für jedes einzelne Wort anzuzeigen. Das verschwendet nur Platz. So sieht es nun aus:

Screenshot des Vokabel-Trainers: Wörterbuch bearbeiten überarbeitet

Nun werden die Flaggen nur noch einmal rechts oben auf dem Bildschirm angezeigt.

Zudem musste ich einen Weg finden, damit der Benutzer Verzeichnisse wieder löschen kann. Lektionen können durch Auswahl und danach Verwendung der Löschen-Schaltfläche in der Command-Bar gelöscht werden. Für Verzeichnisse ist dies nicht möglich, da diese nicht ausgewählt werden können.

Daher habe ich entschieden hierfür eine Art PopUp-Menü zu verwenden: Wenn ein Verzeichnisname berührt/angeklickt wird, soll eine Schaltfläche erscheinen, die es dem Benutzer ermöglicht dieses Verzeichnis zu löschen.

Nach einer Recherche fand ich heraus, dass dies mit einem Flyout möglich ist. Somit habe ich folgendes Quelltext-Stück eingefügt:

<div id="deleteFolderFlyout" data-win-control="WinJS.UI.Flyout" aria-label="{Delete folder flyout}">
    <button id="deleteFolder">Delete this folder with all lessons?</button>
</div>

Um das Flyout letztlich anzuzeigen, wenn der Verzeichnisname berührt/angeklickt wurde, musste ich eine JavaScript-Funktion beim OnClick-Ereignis aufrufen. Aber es ist offensichtlich nur möglich eine JavaScript-Funktion aufzurufen, wenn diese mit einem WinJS-Namespace zur Verfügung gestellt wird:

GroupedItems.ShowDeleteFolderFlyout(event)

Und hier ist die JavaScript-Funktion selbst samt der Namespace-Definition:

function showDeleteFolderFlyout(e) {
    var deleteFolderFlyout = document.getElementById("deleteFolderFlyout");
    deleteFolderFlyout.deleteFolderId = e.target.groupKey;
    deleteFolderFlyout.winControl.show(e.target, "right");
}

WinJS.Namespace.define('GroupedItems', {
    ShowDeleteFolderFlyout: showDeleteFolderFlyout
});

So sieht’s nun aus, wenn man einen Verzeichnisnamen berührt bzw. ihn anklickt:

Screenshot des Vokabel-Trainers: Verzeichnis löschen Flyout

Das war das Update für diese Woche wieder.

Lesen Sie nächsten Montag weiter!

IDF 2012: Treffen mit den anderen Ultimate Coders in San Francisco

Diese Woche findet das Intel Developer Forum (IDF) (Englisch) in San Francisco statt.

Es freut mich sehr wie letztes Jahr von Intel eingeladen worden zu sein.

Diese Jahr wurde ich als Teilnehmer der Ultimate Coder Challenge, aber auch als Intel Black Belt Entwickler eingeladen.

San Francisco ist eine großartige Stadt und es hat viel Spaß gemacht all die anderen Ultimate Coders und Black Belt Entwickler zu treffen. Viele kannte ich bereits von letztem Jahr.

Waren Sie auch bei der IDF 2011?

Intel Ultrabook AppLab in Berlin

Heute war ein Ultrabook AppLab in Berlin, zu welchem ich von Intel eingeladen wurde.

Eine ganze Reihe an Sprechern erklärte die neuen Features der Ultrabooks der nächsten Generation und wie diese von Entwicklern verwendet werden können.

Intel Ultrabook AppLab Berlin

Aber auch eine Sprecher von Microsoft sprach über das neuen Windows-UI-Design von Windows 8.

Und der wichtigste Teil:

Intel Ultrabook AppLab Berlin: Buffet

Wir mussten nicht verhungern und es gab genug Zeit, um sich mit anderen Entwicklern zu unterhalten. ;-)

Waren Sie auch auf diesem AppLab?

Ultimate Coder Challenge: Vokabel-Training

Wie in meinem Blog-Artikel von vergangener Woche angekündigt, werde ich dieses Mal mit dem wichtigsten Teil eines Vokabel-Trainers fortfahren: Dem Vokabel-Training selbst.

Letzte Woche gab es noch eine ganz witzige Veranstaltung von Microsoft hier in München: Ein Windows 8 Hackathon zur App-Entwicklung.

Das war eine gute Gelegenheit ein paar Fragen an kompetente Microsoft-Entwickler zu richten und mit diesem App-Projekt weiter zu kommen.

Vergangene Woche habe ich das Vokabel-Training umgesetzt:

Screenshot des Vokabel-Trainers: Training

Nachdem der Benutzer auf eine Lektion geklickt hat, wird ein Wort zusammen mit dem erwähnten Info-Text zur Übersetzung angezeigt.

Wenn der Benutzer einen Tablett-PC ohne Tastatur hat, kommt automatisch eine virtuelle Tastatur zum Vorschein, nachdem das Textfeld den Fokus erhalten hat:

Screenshot des Vokabel-Trainers: Training Schreiben

Mit dem Klick auf die Prüfen-Schaltfläche zeigt die App eine Nachricht an, ob die eingegebene Übersetzung richtig

Screenshot des Vokabel-Trainers: Training richtig

oder falsch

Screenshot des Vokabel-Trainers: Training falsch

war.

Zum Schluss, nachdem die Lektion abgeschlossen wurde, sieht der Benutzer noch wie viele Wörter richtig und wie viele falsch eingegeben wurden (mein Deutsch ist wohl schon ganz gut ;-) ):

Screenshot des Vokabel-Trainers: Training Statistik

Nun können die hinzugefügten Wörter auch trainiert werden, aber während der Arbeit daran sind mir bereits einige Ideen für Erweiterungen kommen: Beispielsweise wäre es möglich den Benutzer auswählen zu lassen, in welcher Richtung die Übersetzung trainiert werden soll. Auch wäre das Wörter-Kartenspiel, ähnlich wie bei dem alten Vokabel-Trainer, sicherlich ein nettes Feature.

Es ist also noch ausreichend zu tun, aber zunächst müssen noch einige Interface-Sachen ergänzt oder verbessert werden. Auch hierzu habe ich einige gute Ideen von den Microsoft-Jungs letzte Woche bekommen.

Nächste Woche werde ich bei der IDF in San Francisco sein.

Seien Sie also gespannt auf meinen nächsten Artikel in zwei Wochen wieder am Montag!

Windows 8 Hackathon zur App-Entwicklung

Letzte Nacht hat Microsoft einen Windows 8 Hackathon hier in München organisiert.

Windows 8 Hackathon zur App-Entwicklung

Das war die Art von Veranstaltung, die wirklich nur für Entwickler geeignet ist – das sieht man bereits an der Uhrzeit der Veranstaltung: Beginn um 18 Uhr, Ende um 4 Uhr. ;-)

Aber es hat Spaß gemacht dort etwas an meiner ersten App im Metro-Stil für Windows 8 in HTML5 zu arbeiten, besonders, da auch einige kompetente Microsoft-Entwickler für Fragen zur Verfügung standen.

Windows 8 Hackathon zur App-Entwicklung: Essen

… und es gab auch genug zu essen. ;-)

Waren Sie auch schon bei einem Entwickler-Hackathon?

Ultimate Coder Challenge: Funktionalität hinzufügen

In meinem Artikel von letzter Woche schrieb ich über die vorbereitenden Arbeiten, die erforderlich waren, um meinen Vokabel-Trainer in eine App im Metro-Stil – oh, ich meine moderner UI-Stil oder Windows-8-Stil oder wie auch immer das nun genannt werden soll ;-) – für Windows 8 zu verwandeln.

Dieses Mal werden wir etwas richtige Funktionalität zu der App hinzufügen.

Aber bevor ich damit beginnen, möchte ich über ein neues Problem sprechen, auf welches ich während der Entwicklung stieß. Plötzlich startete das Visual Studio nicht mehr und zeigte folgende Fehlermeldung:

Screenshot des Fehlers beim Versuch das Visual Studio zu starten

Er teilte mir mit:

The procedure entry point _Atomic_fetch_sub_4 could not be located in the dynamic link library C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe.

Wie bitte?
Eine immer noch laufende Instanz des Visual Studios funktionierte einwandfrei, aber ich konnte keine neue starten!

Die einzige Sache (neben der Entwicklung), die ich seit dem letzten Neustart gemacht habe, war die Installation einiger Windows-Live-Apps (um den Windows Live Writer zu bekommen). Ich suchte im Internet und, tatsächlich, das war das Problem. Offenbar gab es einige Inkompatibilitäten zwischen diesem und der installierten Version des Visual Studios. Aber, glücklicherweise, gab es bereits einen Bug-Fix von Microsoft.

Solche Sachen kosten immer Zeit, aber was soll’s, alles ist noch beta. ;-)

Gut, nun machen wir mit der App weiter.

Am Ende meines letzten Artikels machte ich die Lektionen auswählbar und fügte die App-Bar hinzu:

Screenshot des Vokabel-Trainers: App-Bar

Als nächster Schritt benötigt die Schaltfläche “Wörterbuch ändern” etwas Funktionalität. Dazu habe ich eine neue Seite erstellt, auf welcher jedes Wort des Wörterbuchs einer Lektion wieder in einem Grid, um im UI-Design zu bleiben, angezeigt wird:

Screenshot des Vokabel-Trainers: Wörterbuch bearbeiten

Sie sehen, dass nicht nur die Wörter in beiden Sprache angezeigt werden, sondern auch ein kurzer Info-Test für jedes Wort. Wird ein neues Wort dem Wörterbuch hinzugefügt, kann der Benutzer so einen Info-Text eingeben, um einen Hinweis für die Übersetzung zu liefern. Im Beispiel habe ich diesen genutzt, um das Wort in den Kontext eines Satzes zu setzen. Dies in eine Hilfestellung für Anfänger und sollte auch den Lernerfolg erhöhen.

Um die Möglichkeit zu haben Wörter zu ändern oder zu löschen, können Wörter genauso wie die Lektionen auf der vorangegangenen Ansicht ausgewählt werden, was wieder eine App-Bar hervor bringt:

Screenshot des Vokabel-Trainers: Wörterbuch bearbeiten App-Bar

Nun kann der Benutzer ein bestehendes Wort ändern oder ein neues hinzufügen:

Screenshot des Vokabel-Trainers: Wort bearbeiten

Zu diesem Zeitpunkt können bereits Wörter zu dem Wörterbuch hinzugefügt und somit Lektionen erstellt werden. Aber der wichtigste Teil fehlt noch: Das richtige Vokabel-Training.

Darum werde ich mich nächste Woche kümmern.

Lesen Sie also nächsten Montag weiter!