.
Anmeldung | Registrieren | Hilfe

.NET-Blogs Archiv Januar 2012

BlackBerry Business Cloud Services fuer Microsoft Office 365

31.01.2012 09:11:07 | Kay Giza

Microsoft Exchange Online auf dem Smartphone genießen können ab sofort auch Nutzer eines BlackBerry®-Gerätes: Dank der von BlackBerry-Hersteller Research in Motion (RIM) gehosteten Business Cloud Services für Microsoft Office 365, die nach mehrmonatiger öffentlicher Betaphase jetzt offiziell freigegeben wurden, profitieren BlackBerry-Nutzer im Rahmen von Office 365 für mittelständische und große Unternehmen oder Exchange Online ab sofort ohne weitere Kosten von der Synchronisation ihres Smartphones mit Microsoft Exchange Online. Gute Nachrichten auch für Administratoren, die mit der Dienstintegration in das Office 365-Administrationsportal leichtes Spiel haben. Erfahren Sie mehr über die BlackBerry Business Cloud Services für Microsoft Office 365... [... mehr in diesem Blogeintrag auf Giza-Blog.de]

This post is powered by www.Giza-Blog.de | Giza-Blog.de: RSS Feed
© Copyright 2006-2012 Kay Giza. All rights reserved. Legal
Subscribe

Call for Papers der dotnet Cologne 2012 ist noch aktiv

30.01.2012 13:58:29 | Albert Weinert

Wer es noch nicht mitbekommen hat, am 4. Mai 2012 findet die 2012er Ausgabe der dotnet Cologne 2012 statt. Wir suchen natürlich noch Sprecher, mit interessanten Themen die wir unseren Teilnehmern anbieten können.

Mir persönlich fehlen noch ein paar Vorträge Absatz des Microsoft Stacks, es gibt Interessante Open Source Tools und Frameworks rund um .NET die noch nicht mit einem Vortrag bedacht sind. Mir liegt viel daran auch dort entsprechendes zu Präsentieren.  Von der Einführung bis zum Deep Dive darf alles angeboten werden. Macht die Konferenz Interessant, was für Ihre selbst gerne mal auf einer Konferenz sehen.

Also holt euch euren Zugang zum SpeakerNet der dotnet Cologne und tragt eure Vorschläge ein.

Hier geht es zu unserem Call for Papers https://dotnet-cologne.de/CallForPapers.ashx

See# Conference 2012

30.01.2012 13:21:00 | Jürgen Gutsch

Vor einigen Wochen habe ich per Doodle eine kleine Stimmungsumfrage gestartet, um zu sehe, wie das Interesse an einer weiteren Veranstaltung des .NET-Stammtisch Konstanz-Kreuzlingen aussieht.

Kurz nach dem ersten Ansturm auf die Umfrage ist das neue Team dann zusammengesessen und hat überlegt, ob und wie die neue Veranstaltung denn konkret aussehen soll. Uns war wohl allen klar, dass wir die Veranstaltung auf jeden Fall noch einmal versuchen wollen, sofern die Umfrage positiv verläuft. Und so wie es hier aussieht nenne ich das sehr positiv:

Ich möchte mich bei allen Teilnehmern der Umfrage hiermit ganz herzlich bedanken. Dieses Ergebnis hat unsere Motivation für eine weitere Veranstaltung noch mehr verstärkt.

Das Team

Im Team gab es ein paar Veränderungen. So wird uns Golo Roden – der letztes Jahr eine großartige Agenda mit vielen tollen Sprechern aufgestellt hat - leider nicht mehr aktiv im Team unterstützen. Auch Markus Schmid möchte sich dieses Jahr nicht mehr an der Organisation der Veranstaltung beteiligen.

Wenn auch nur im Beck-End, so bekommen wir doch starke Unterstützung von Patrick Kress, der die organisatorischen Fäden (Zügel?) zusammenhalten wird.

Weiterhin mit dabei sind Stefan Zybarth (Combit GmbH) für PR und Helfer, Tilo Schinke (Ontrex AG) für Finanzen, Catering und Location und zu guter Letzt meine Wenigkeit als Ansprechpartner für Sponsoren, Sprecher und Teilnehmer.

Für die Auswahl der Themen möchten wir dieses mal die .NET-Community beauftragen ;-)
Parallel zum CfP starten wir eine Umfrage zur Themenwahl. Sprecher und Vorträge werden wir dann anhand der gewählten Themen aus den Eingängen des CfP auswählen.

Neuer Name

Die Änderung des Namens hatte mehrere Gründe: Zum einen gab es nie eine Party (außer die traditionelle Kennenlern-Party am Vortag) und zum anderen gab es auf der Seiten der Teilnehmer Schwierigkeiten vom Arbeitgeber eine Party am Samstag gezahlt zu bekommen.

Zum anderen wollen wir uns auf das Konferenz-Schema festlegen, da es in dieser Region keine Konferenz dieser Art gibt. Auch wenn es in der .NET-Community den Anschein hat, dass es inzwischen reichlich Veranstaltungen der .NET-Community gibt, so sind es doch viele verschiedene Arten und keine welche den Bodenseeraum und alle vier anliegenden Länder ansprechen soll.

Die Website wird in Kürze unter der Adresse seesharp-conference.net erreichbar sein. Unser Sponsor und Hosting Provider die K&K Internet GmbH wird die nötigen Einstellungen im IIS noch machen müssen und wir werden noch ein paar Änderungen auf der Website machen müssen.

Als Twitter-Hashtag wird wohl #SSC12 herhalten.

Location und Termin

Die See# Conference wird, wie die Veranstaltungen zuvor wieder im DREISPITZ Sport- und Kulturzentrum in Kreuzlingen statt finden. Hier sind wir gut betreut, fühlen uns wohl, der Caterer hat eine Küche vor Ort. Weiterhin bekommen wir als Kreuzlinger Verein die Location zum halben Preis und die Stadt Kreuzlingen freut sich, dass sie auch eine IT-Veranstaltung im Angebot hat :-)

Was den Termin angeht, so können wir unser Versprechen, einen Termin außerhalb der Sommerferien zu finden, leider nur für die Schweiz einlösen. Der Termin für die See# Conference 2012 wird

Freitag der 31. August 2012

sein. Das war der einzige Termin der im Spätsommer, bzw. Herbst noch frei war. Das nächste mal werden wir wohl schon 14 Monate im Voraus buchen müssen. Allerdings spricht das ja auch für das DREISPITZ. Vielen Dank - an dieser Stelle - an die Stadt Kreuzlingen für die Unterstützung bei der Terminfindung. (Ich freu mich schon jetzt wieder auf die interessanten Gespräche mit dem Hauswart Herrn Keller *fg*)

Verpflegung

Erst der Negative Punkt: Bei der letzten Veranstaltung mussten wir sehr viele Flaschen selber einsammeln und in die bereitgestellten Behälter entsorgen, aber das alleine ist nicht das Problem, sondern die Tatsache, dass die ca. Hälfte dieser Flaschen nicht ganz lehr waren, bzw. teilweise noch mehr als halb voll waren. Da der Inhalt der Flaschen einen gewissen Wert besitzt der auf die Teilnehmer umgeschlagen werden muss und da es einfach nur schade darum ist Lebensmittel entsorgen zu müssen, wollen wir das aus Ökologischen und Ökonomischen gründen von vornherein begrenzen. Wir werden deshalb, wie bei der ersten Veranstaltung, nur drei Getränke kostenfrei bereitstellen. Alle weiteren Getränke werden zum Selbstkostenpreis abgegeben. Außerdem werden wir ein Flaschenpfand einführen.

Die positiven Punkte: Der negative Punkt gilt nur für Softdrinks in Flaschen. Kaffee und Tee gibt es natürlich weiterhin kostenfrei. :-) Als Caterer werden wir schauen dass wir wieder das Hotel ZIIL bekomme können. Im Gegensatz zum Caterer der ersten See# Party, lief die Abwicklung mit dem Hotel ZIIL absolut stressfrei und lecker war es auch.

Also…

…alle die in der Umfrage für die Veranstaltung gestimmt haben möchte ich auch auf der See# Conference sehen ;-)

Ich freue mich drauf ein drittes mal eine solche Veranstaltung machen zu können und lade alle herzlich dazu ein, als Teilnehmer, als Sponsor oder als Sprecher, das Event einen noch größeren Erfolg werden zu lassen als die vergangenen Veranstaltungen :-)

TFS 11 : Master und Sub Team Backlog Management

30.01.2012 13:17:57 | Christian Binder

Manche Organisationen haben für das Product Backlog Management ein zentrales Master Backlog, von welchem die Product Backlog Items (PBI) dann verschieden Sub-Teams zugewiesen werden. Diese Teams arbeiten in Ihrem eigenen separaten Product Backlog. Mit TFS 11 können wir nun dieses Konzept direkt konfigurieren, dabei wird der AreaPath verwendet um die Hierarchie abzubilden.

image

Master Backlog:

image

Die Zuweisung zu einem Team Backlog erfolgt über den AreaPath des PBI’s:

image

Dann findet man im Sub Team Backlog das PBI. Über die Konfiguration kann festgelegt werden, ob dass PBI noch im Master Backlog nach einem Refresh sichtbar sein soll oder nicht.

image

Wie konfiguriere ich das Ganze? Gregg hat einen Post verfasst, wie man Schritt für Schritt das Master Sub-Team Konzept konfiguriert.
Hinweis: In dem TFS 11 CTP Build ist diese Funktionalität nicht enthalten, erst mit der TFS 11 Beta oder jetzt schon mit dem TFS Service.

Giza-Blog.de: Office 365 Domain- und Dienstkonfigurationsanleitungen haben ein neues zu Hause gefunden

30.01.2012 09:57:41 | Kay Giza

Letztes Jahr habe ich hier im Blog Anleitungen bzw. How-To-Guides rund um die Dienstkonfiguration von Office 365 für verschiedenste Hoster veröffentlicht. Wie füge ich bei Office 365 meine Domain (bzw. Domäne) hinzu und lasse sie überprüfen? Wie richte ich bei Office 365 die Dienste Exchange Online, Lync und SharePoint ein? Herausgekommen sind 20 sehr umfangreiche Anleitungen. Damit diese stetig aktuell sind, auch von jedermann bearbeitbar sind (denn Sie als Office 365 Anwender bzw. Administrator machen sicherlich ihre ganz eigenen Erfahrungen und sammeln auch Tipps und Tricks), haben wir die Anleitungen in das offizielle Microsoft Office 365 Wiki gestellt. Bitte beachten Sie daher... [... mehr in diesem Blogeintrag auf Giza-Blog.de]

This post is powered by www.Giza-Blog.de | Giza-Blog.de: RSS Feed
© Copyright 2006-2012 Kay Giza. All rights reserved. Legal
Subscribe

Silverlight und Spekulationen rund um das Thema

28.01.2012 14:48:00 | Jürgen Gutsch

Eigentlich habe ich das Thema inzwischen satt, ich beobachte es schon seit knapp einem Jahr und nirgends sind klare Aussage zu finden, sondern nur wilde Spekulationen. Das ging im letzten halben Jahr nicht nur so weit, dass Silverlight in Frage gestellt worden ist, sondern auch das .NET Framework.

Klar ist, dass von Microsoft keine klaren Informationen zu dem Thema kommen. Klar ist dass es dadurch etwas Verunsicherung beim Thema Silverlight gibt.

Ich teile die Meinung, dass Silverlight-Projekte im Moment eine schlechte Idee seien, absolut nicht. Vielleicht bin ich aber auch nicht paranoid genug… ;-)

Wie auch immer… komme ich im Moment entwickelnd und beratend mit einigen neuen Silverlight-Projekten in Berührung. Es stehen auch einige Anfragen an… Aus meiner Sicht gibt es im Moment keinen Grund zu behaupten, dass Silverlight tot ist. Andererseits gibt es auch keine Informationen ob es ein Silverlight 6 geben wird oder nicht. Im Gegenteil konzentriert sich Microsoft auf HTML5

Aber ist das schlimm? Könnte das ein Problem für Silverlight sein?

Aus meiner Sicht nicht. Denn in einem einzigen Punkt stimme ich mit Steve Jobs (RiP) überein. Silverlight und Flash haben im Web nichts zu suchen und hatten es auch nie. Flash hatte sich fälschlicherweise fast als ein Standard im Web durchgesetzt. Kein Wunder, war es bis zu Silverlight doch auch die einzige Möglichkeit schnell schöne Rich Internet Applications zu schreiben. Ich habe selber habe (nicht nur fürs Web) Anwendungen mit Flash erstellt.

Silverlight ist eine Alternative zu Flash, die sich zwar als Technologie, aber im Web kaum durchgesetzt hat. (Allerdings: Erst vor ein paar Monaten hat Amazon den Videoplayer für die Filme auf lovefilm.de von Flash auf Silverlight ändern lassen.) Das hat sicher auch einigen klar gemacht, dass beide Technologien ihre Daseinsberechtigungen haben, aber nicht im Web, sprich nicht für alle Benutzer und nicht für alle Endgeräte. Wieso auch…

Dafür gibt es bereits einen Standard und der heißt HTML. ;-)

Jetzt mit HTML5 haben auch die Videoplayer mit Flash oder Silverlight keine Daseinsberechtigung mehr. Und das ist auch gut so, so ist es möglich eine Website mit allen Inhalten, für alle Benutzer und allen Endgeräten zur Verfügung zu stellen. Genial oder? Ich finde es jedenfalls genial…

Und wo hat Flash und Silverlight noch eine Daseinsberechtigung?

Überall dort wo HTML aufhört,  bzw. überall dort wo HTML zu aufwendig wäre und überall dort wo die Zielgruppe eingeschränkt ist. In den aktuellen Projekten, an denen ich beteiligt bin, ist die Zielgruppe begrenzt, bzw. den Benutzern kann also die Systemvoraussetzungen genannt werden. Bei allen Projekten handelt es sich um Geschäftsanwendungen.

Und Silverlight 6? Benötigen wir ein Silverlight 6?

Wenn die Tatsache stimmt, dass die XAML-Schicht mit Silverlight 5 und WPF 4.5 identisch sein kann, so wird Silverlight 6 nicht mehr benötigt. Wieso auch? Wir haben dann eine Technologie mit der Bezeichnung XAML mit C#, bzw. XAML mit VB. Basierend auf unterschiedlichen Frameworks. Ehrlich gesagt, finde ich diese Vorstellung gar nicht mal so übel…

Einzig eine Frage die ungeklärt ist, ist das Silverlight-Plug-In… Aber Moment mal… Hat sich Microsoft, nicht selber verpflichtet jedes Produkt mindesten zehn Jahre zu supporten?

Nebenher: Wer glaubt eigentlich wirklich, dass eine Software zehn Jahre lang aktuell bleibt?

Wir können also noch ein paar Jahre XAML mit C# oder VB im Silverlight Plug-In laufen lassen… Und dann ist .NET fast zwanzig Jahre alt… Und dann? Möglicherweise wird das Plug-In dann nicht mehr Silverlight heißen… Möglicherweise auch ganz was anderes…

Ich möchte hier nicht auch noch anfangen zu spekulieren, sondern nur sagen, dass ich mir erst mal keine Sorgen um die Technologie Silverlight mache. Das heißt nicht, dass man nicht dennoch über den Tellerrand schauen sollte um anderes und neues zu lernen. Ganz im Gegenteil… ;-)

Google API jQuery UI 1.7.2 Theme Übersicht + Razor-Layout

24.01.2012 15:02:13 | Mario Priebe

Im folgenden eine kleine Übersicht von Google API jQuery UI 1.7.2 Designs, so vorbereitet, dass diese schnell im Header eines Razor Layouts eingefügt werden können. base <link href="@Url.Content("http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/base/jquery-ui.css")" rel="Stylesheet" type="text/css" /> blitzer <link href="@Url.Content("http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/blitzer/jquery-ui.css")" rel="Stylesheet" type="text/css" /> dark-hive <link href="@Url.Content("http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/dark-hive/jquery-ui.css")" rel="Stylesheet" type="text/css" /> eggplant <link href="@Url.Content("http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/eggplant/jquery-ui.css")" rel="Stylesheet" type="text/css" /> flick <link href="@Url.Content("http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/flick/jquery-ui.css")" rel="Stylesheet" type="text/css" /> [...]

Video-Reihe: Windows Intune, Office 365 und Dynamics CRM Online - von der Testversion bis hin zum Produktivsystem

23.01.2012 15:12:52 | Kay Giza

Es freut mich heute einige neue How-To-Guides unserer Video-Reihe Ihr-Unternehmen-in-der-Cloud.de vorstellen zu dürfen. Zielgerichtet in einzelnen Video-Kapiteln, oder kompakt in 1 ½ Stunden, erfahren Sie, wie man Windows Intune, Office 365 und Dynamics CRM Online von der ersten Sekunde an nutzen kann. Es wird gezeigt, wie man sich für die kostenlosen und unverbindlichen Testversionen registriert, die ersten Schritte mit dem jeweiligen Produkten und Services macht und von der Testversion in ein Produktivsystem übergeht. Verschaffen Sie sich so einen umfangreichen Überblick über die Cloud-Angebote von Microsoft für kleine und mittelständische Unternehmen. Aufgegliedert nach verschiedenen Produkten & Kapiteln... [... mehr in diesem Blogeintrag auf Giza-Blog.de]

This post is powered by www.Giza-Blog.de | Giza-Blog.de: RSS Feed
© Copyright 2006-2012 Kay Giza. All rights reserved. Legal
Subscribe

FileNotFoundException im Konstruktor von SPSite

22.01.2012 20:06:00 | Martin Hey

Als ich eben den Post zu AddFieldAsXml geschrieben habe, habe ich die Beispiele in einer Konsolenanwendung nachgestellt. Das Beispiel ist nicht sehr kompliziert und doch überraschte mich SharePoint direkt in der ersten Zeile mit einer FileNotFoundException.

Laut MSDN wird eine FileNotFoundException im SPSite-Konstruktor dann geworfen, wenn die SiteCollection unter der Url nicht gefunden werden konnte. Die Url ließ sich jedoch problemlos im Browser aufrufen - sowohl unter localhost als auch unter dem Rechnernamen wurde die SiteCollection gefunden. Nächster Versuch war also, die Credentials explizit mitzugeben, auch wenn das eigentlich nicht das Problem sein dürfte, weil sowohl Browser als auch Visual Studio mit dem gleichen Nutzeraccount verwendet wurden.

Was die MSDN-Seite verschweigt: Diese Exception wird auch dann geworfen, wenn das Platform-Target nicht stimmt. Konsolenanwendungen haben in der Visual Studio Vorlage grundsätzlich erst einmal das Platform Target x86; SharePoint aber ist eine 64-bit-Anwendung, daher muss das Platform Target der Konsolenanwendung auch x64 sein, damit es funktioniert. Also die Einstellung eben geändert, neu kompiliert und schon klappt es auch von der Konsole.

AddFieldAsXml - Bug oder Feature, das ist hier die Frage

22.01.2012 18:27:00 | Martin Hey

Möchte man programmatisch Felder zu einer SharePoint-Liste hinzufügen, so stolpert man früher oder später über die Methoden Add bzw. AddFieldAsXml von SPFieldCollection. In vielen Fällen führen beide Methoden zum Ziel, wobei AddFieldAsXml den Vorteil hat, dass man recht einfach das Schema-Xml aus bereits bestehenden Listen übernehmen kann, es auch recht komplexe Szenarien zulässt und dann in meinen Augen besser lesbar ist als Quellcode, der über mehrere Zeilen oder Klassen verteilt versucht, ein Objekt vom Typ SPField zu erzeugen und mit den passenden Eigenschaften zu bestücken.

Damit möchte ich auch schon zum Problem kommen: Ein Objekt vom Typ SPField verfügt über zwei Eigenschaften, die in diesem Kontext eine Rolle spielen: Title stellt in der Liste den Spaltennamen dar, den der Nutzer zu Gesicht bekommt. Dieser kann natürlich auch Leerzeichen oder Sonderzeichen beinhalten. Im Gegensatz dazu ist InternalName die interne Referenz auf die Spalte und als solche ist sie in der jeweiligen Liste eindeutig und readonly. Zudem werden hier sämtliche Sonderzeichen maskiert dargestellt. Um es mal plastisch darzustellen im folgenden das Beispiel aus der MSDN.

using (var site = new SPSite("http://localhost/"))
{
    using (var web = site.RootWeb)
    {
            var list = web.Lists["Shared Documents"];

            var displayName = "My Custom Field";
            var staticName = "MyStaticName";

            var strInternalName = list.Fields.Add(displayName, SPFieldType.Text, false);
            var field = list.Fields.GetFieldByInternalName(strInternalName);

            field.StaticName = staticName;
            field.Update();
    }
}

In diesem Fall ist Title nun wie erwartet My Custom Field und der Internal Name My_x0020_Custom_x0020_Field.

Wie bereits angedeutet, geht das ganze auch mit AddFieldAsXml:

using (var site = new SPSite("http://localhost/"))
{
    using (var web = site.RootWeb)
    {
        var list = web.Lists["Shared Documents"];

        var fieldXml = "<Field Type=\"Text\" MaxLength=\"50\" DisplayName=\"My Custom Field\" ID=\"15C0D97B-3735-4AD9-8FE2-8A01E5B43486\" StaticName=\"MyStaticName\" Name=\"MyInternalName\" />";
        var strInternalName = list.Fields.AddFieldAsXml(fieldXml);

        var field = list.Fields.GetFieldByInternalName(strInternalName);

        field.Update();

    }
}

Was bei der Ausführung nun auffällt: Obwohl ich im XML einen Internal Name vorgegeben habe, wird dieser nicht verwendet, sondern weiterhin auf Basis des Display Name ein Internal Name generiert. Das ist insofern schlecht, da wie beschrieben der Internal Name ja der Identifier der Spalte ist und deshalb auch in CAML-Queries verwendet wird.

Aber mal unabhängig davon gibt es natürlich auch hier mehrere Arten das Problem zu lösen: Erster Ansatz und einer der auch häufig verwendet wird, ist, im Aufruf von AddFieldAsXml DisplayName und InternalName auf den künftigen InternalName zu setzen und im Nachhinein den DisplayName programmatisch auf den eigentlichen Wert zu setzen. Diesen Ansatz verfolgen zum Beispiel Bil und auch Torsten.

Wenn man sich die Blogbeiträge so anschaut und sieht, dass dieses Verhalten schon mindestens seit 2005 besteht, so stellt sich hier doch die Frage nach Bug oder Feature und warum es dafür keine saubere Lösung gibt. Gibt es nicht? Doch, die gibt es, aber man muss drauf kommen.

AddFieldAsXml hat noch eine zweite Überladung und hier liegt der Schlüssel zum Erfolg:

using (var site = new SPSite("http://localhost/"))
{
    using (var web = site.RootWeb)
    {
        var list = web.Lists["Shared Documents"];

        var fieldXml = "<Field Type=\"Text\" MaxLength=\"50\" DisplayName=\"My Custom Field\" ID=\"15C0D97B-3735-4AD9-8FE2-8A01E5B43486\" StaticName=\"MyStaticName\" Name=\"MyInternalName\" />";
        var strInternalName = list.Fields.AddFieldAsXml(fieldXml, true, SPAddFieldOptions.AddFieldInternalNameHint);

        var field = list.Fields.GetFieldByInternalName(strInternalName);

        field.Update();

    }
}

Verwendet man hier explizit die Option AddFieldInternalNameHint, nur dann wird der im Xml angegebene interne Name auch verwendet.

 

Ich hätte erwartet, dass man das auch direkt anhand des Schema-XMLs hätte ermitteln können - à la: Attribut Name vorhanden, dann verwenden, sonst anhand des DisplayNames. Aber so ist es leider nicht. Nehmen wir es also als Sicherheits-Feature hin, dass man die Vergabe des Internal Names explizit noch einmal mit setzen der Option AddFieldInternalNameHint bestätigen muss.

Englische Version Englische Version

H&D Talk: Windows 8 Preview

21.01.2012 06:48:03 | Lars Keller

Karim und ich haben zusammen eine Reihe von kleinen Filmen (1-6 Teile) aufgenommen, wo wir über die Windows 8 Developer Preview und das passende Samsung Slate von der //BUILD/ Konferenz sprechen.

Wir geben einen Überblick über die neuen Funktionalitäten und zeigen warum Windows 8 ein interessantes Tablett Betriebssystem werden kann. Metro-Oberfläche ist in aller Munde! Teil 5 & 6 zeigen wie einfach man für diese programmieren kann.

Link: www.windows-8-preview.de

Feedback zu den Filmen ist willkommen! :-)

INotifyPropertyChanged ohne Magic Strings mit Prism 4

20.01.2012 20:05:00 | Martin Hey

Wer mit WPF zu tun hat, kennt das: Damit die Benutzeroberfläche richtig aktualisiert wird, müssen die ViewModels INotifyPropertyChanged implementieren und das große Problem dabei ist, dass die PropertyChangedEventArgs den Namen der Eigenschaft als String erwarten. Wenn man sich konzentriert, ist das initial auch nicht allzu schwierig. Problematisch kann es dann werden, wenn man Refactorings durchführt und dann vergisst, den String anzupassen.

using System.ComponentModel;

public class MainViewModel : INotifyPropertyChanged
{
    private string zahl1;

    public event PropertyChangedEventHandler PropertyChanged;

    public string Zahl1
    {
        get
        {
            return this.zahl1;
        }

        set
        {
            this.zahl1 = value;
            this.RaisePropertyChanged("Zahl1");
        }
    }

    private void RaisePropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Dieses Problem kann man sehr elegant mit AOP umgehen - zum Beispiel mit einem Aspekt mit PostSharp. Diese Lösung finde ich persönlich sehr elegant, jedoch kann oder möchte man dieses Produkt nicht immer einsetzen. Deshalb möchte ich hier kurz auf eine andere Alternative hinweisen.

In vielen WPF-Projekten wird Prism eingesetzt, um Composite Applications zu erzeugen. Prism selbst bringt ein Basisobjekt mit, das man für die ViewModels verwenden kann - NotificationObject. Vorteil dieses Basisobjekts ist es, dass dieses bereits den Event und die Methode RaisePropertyChanged zum Aufruf beinhaltet. Damit würde das oben angebrachte Beispiel dann wie folgt aussehen:

using Microsoft.Practices.Prism.ViewModel;

public class MainViewModel : NotificationObject
{
    private string zahl1;

    public string Zahl1
    {
        get
        {
            return this.zahl1;
        }

        set
        {
            this.zahl1 = value;
            this.RaisePropertyChanged("Zahl1");
        }
    }
}

Damit ist das ViewModel schon etwas entschlackt, aber das Problem mit den Magic Strings besteht noch immer. NotificationObject bietet noch eine weitere Überladung für RaisePropertyChanged, in der man eine Expression übergeben kann, aus der der Name der Property dann extrahiert wird.

using Microsoft.Practices.Prism.ViewModel;

public class MainViewModel : NotificationObject
{
    private int zahl2;

    public int Zahl2
    {
        get
        {
            return this.zahl2;
        }

        set
        {
            this.zahl2 = value;
            this.RaisePropertyChanged(() => this.Zahl2);
        }
    }

}

Wenn man mal hinter die Kulissen schaut, dann sieht man, dass die Magie von der Methode PropertySupport.ExtractPropertyName übernommen wird. Lässt man nun hier mal alles weg, was mit Parameterprüfung zu tun hat, dann reduziert es sich auf einen Zweizeiler, der Gebrauch vom Namespace System.Linq.Expressions macht.

private void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression)
{
    var propertyName = ExtractPropertyName(propertyExpression);
    this.RaisePropertyChanged(propertyName);
}

private static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
{
    var memberExpression = propertyExpression.Body as MemberExpression;
    return memberExpression.Member.Name;
}

Man könnte wenn man wollte also diese Methode auch ohne eine Referenz auf Prism implementieren. System.Linq.Expressions selbst verwendet intern (wie sollte es anders sein) Reflection - und wie immer, so ist die Ermittlung von Werten zur Laufzeit langsamer als das Kompilieren von Konstanten, so wie es mit dem Hinterlegen des Namens der Eigenschaft als String oder mit PostSharp passieren würde. In meinen Augen ist der Geschwindigkeitsnachteil aber in den meisten Fällen vernachlässigbar klein.

Englische Version Englische Version

Skype aus dem Team Explorer heraus mit den TFS Power Tools 2010 nutzen

20.01.2012 17:34:27 | Christian Binder

Das AIT Team System Pro Team einen Skype Provider für VS 2010 auf Codeplex bereit gestellt. Über die Team Member Funktion kann man als Team Explorer Nutzer sehr einfach andere Instant Messaging Programme einbinden. Die Einbindung umfasst dabei nicht nur die Kommunikation über Textnachrichten, sondern in Abhängigkeit vom Client auch über Voice over IP (VOIP) oder Video. Also mal schnell jemanden aus dem Team “anpingen” ohne Visual Studio verlassen zu müssen.

image

Alle Details gibt’s auf dem AIT Blog.

Treffen der DNUG Braunschweig–Windows 8 für Entwickler

20.01.2012 09:12:00 | Lars Keller

Die DNUG Braunschweig trifft sich am 25.01.2012 um 19:00 im Restaurant Zucker (Tagungsraum). Dieses Mal halten Karim und ich einen Vortrag zur Windows 8 Entwicklung.

Abstract:
Seit September 2011 gibt es die erste Preview Version von Windows 8 und die Beta steht bereits vor der Tür. So langsam wird es Zeit sich mit den Neuerungen und Änderungen des neuen Betriebsystems zu beschäftigen. Mit der neuen Metro-Welt für Tablet-PCs führt Microsoft auch einen neuen App Store ein. Wie auch schon beim Window Phone 7 ergibt sich hier für Entwickler ein neuer Markt für die Vertreibung der eigenen Software.
Lars Keller und Karim El Jed machen einen kleinen Rundflug durch die neue Windows 8 Welt und zeigen wie man eine Metro-Applikation mit der Windows Runtime entwickeln kann.

Wie immer ist die Veranstaltung kostenlos! Weitere Informationen zur DNUG Braunschweig können hier gefunden werden: http://www.dotnet-braunschweig.de

Neuauflage: Kostenfreier Vortragsabend: Sicherheit mit der Cloud am 30.01.12 bei Microsoft Koeln

16.01.2012 09:13:24 | Kay Giza

Nach dem großen Erfolg der ersten Abendveranstaltung Rechtliche und technische Sicherheit mit der Cloud [Kostenfreie Abendveranstaltung] am 28.11.2011, findet in einer Neuauflage am Montag, 30. Januar 2012 um 17:00 - dieses mal bei Microsoft in Köln - erneut eine Abendveranstaltung von Microsoft zum Thema Sicherheit mit der Cloud statt. Diese Abendveranstaltung widmet sich - wie schon der erste Vortragsabend im November letzten Jahres - dem Thema Sicherheit mit der Cloud und bietet Raum über Ihre grundlegenden Fragen zu rechtlichen und technischen Sicherheitsthemen im Zusammenhang mit der Cloud zu diskutieren. Während und nach den Vorträgen wird es Gelegenheit geben, sich mit den Referenten und anderen Interessierten vor Ort auszutauschen... [... mehr Informationen in diesem Blogeintrag auf Giza-Blog.de]

This post is powered by www.Giza-Blog.de | Giza-Blog.de: RSS Feed
© Copyright 2006-2012 Kay Giza. All rights reserved. Legal
Subscribe

Meine nächsten Vorträge “Kinect & VSTO”

16.01.2012 09:07:00 | Lars Keller

Ich bin mal wieder mit dem Thema Kinect & MS Office Entwicklung (VSTO) unterwegs.

Am 17.01.12 bei der DNUG Rhein-Neckar ab 18:30

und

am 18.01.12 bei der DNUG Saar ab 18:00 Uhr

Abstract:

Microsoft hat vor kurzen das Kinect SDK vorgestellt. Lässt sich durch Kinect eine völlig neue User Experience herstellen oder ist das doch nur eine „Fuchtelsteuerung“? Passt das zu MS Office? In dieser Session tauchen wir in das Kinect SDK ein und schauen uns an wie dieses mit VSTO (Visual Studio Tools for Office) genutzt werden kann. Eines verspricht dieser Vortrag mit Garantie, es wird eine Benutzerinteraktion geben!

Wir sehen uns dort! :-)

Arbeiten bei Microsoft: Cloud Project Manager und MVP Program Coordinator

11.01.2012 16:56:06 | Kay Giza

Wir stellen ein! Microsoft sucht derzeit Verstärkung und gerne möchte ich auf zwei offene Stellen bei Microsoft hinweisen. Falls Sie Interesse an einer dieser Stellen haben und die Herausforderung gerne annehmen möchten, bewerben Sie sich bitte offiziell über eines der vielen Job-Portale. Dort finden Sie auch eine ausführliche Stellenbeschreibung. Cloud Marketing Project Manager sowie MVP Program Coordinator... [... mehr in diesem Blogposting auf Giza-Blog.de]

This post is powered by www.Giza-Blog.de | Giza-Blog.de: RSS Feed
© Copyright 2006-2012 Kay Giza. All rights reserved. Legal
Subscribe

Microsoft (Office 365) ist gleich Mittelstand [kostenfreies Whitepaper zum Download]

11.01.2012 16:23:22 | Kay Giza

TechConsult hat am 20.12.2011 bereits das 22 Seiten Whitepaper veröffentlicht, siehe New-Meldung: Microsoft Office 365 setzt sich vor die Konkurrenz. Das Whitepaper ist ist in 5 Kapitel gegliedert und befasst sich umfassend damit, Unternehmen auf der Suche nach Lösungen der Zusammenarbeit in der Cloud eine Entscheidungshilfe zur Anbieterauswahl an die Hand zu geben. Unter dieser Prämisse wurden Cloud-Angebote von 1&1, Google, IBM, Microsoft, o2 und Telekom einem praxisnahen Vergleich unterzogen und bewertet. Die Kapitel... [... mehr in diesem Blogeintrag auf Giza-Blog.de]

This post is powered by www.Giza-Blog.de | Giza-Blog.de: RSS Feed
© Copyright 2006-2012 Kay Giza. All rights reserved. Legal
Subscribe

Neue Version von "Sag's anders" released

05.01.2012 23:36:00 | Martin Hey

Vor etwa einem Jahr ging meine App Sag's anders im Windows Phone Marketplace live. Die Idee dazu kam mir, als ich zufällig bei der Suche nach einem Synonym über das Projekt OpenThesaurus gestolpert bin.

Was ist OpenThesaurus?

OpenThesaurus ist ein freies deutsches Synonymwörterbuch. Das bedeutet in erster Linie, dass man hier Wörter gleicher oder ähnlicher Bedeutung nachschlagen kann. Aber Nachschlagen ist nicht alles. Ähnlich einem Wiki kann man sich auf der Webseite auch anmelden und selbst Synonyme eintragen.

Was ist Sag's anders?

Sag's anders ist ein Windows Phone 7 Client, der die API von OpenThesaurus anbindet. Damit kann man nun direkt im Phone eine Synonymsuche anstoßen. Leider bietet die API von OpenThesaurus keinen schreibenden Zugriff, so dass man zum Eintragen von Synonymen weiterhin über die Webseite gehen muss.

Seit über einem Jahr nun ist Sag's anders im Windows Phone Marketplace vertreten und war damit eine der ersten Apps. Inzwischen wurde die App über 28.000 mal heruntergeladen. Was als Lernprojekt für eine neue Technologie begann ist damit über die Zeit ein voller Erfolg geworden. Inzwischen ist die Zeit für ein Update gekommen - und was soll ich sagen: Sag's anders Version 1.2 ist jetzt im Marketplace verfügbar.

Und abgesehen vom Upgrade der Frameworkversion von Windows Phone 7 zu Windows Phone 7.1 gibt es auch einige neue Features:

  • Nachschlagen: Wurde eine Synonymsuche durchgeführt, kann das Suchwort in der deutschsprachigen Wikipedia-Seite nachgeschlagen werden.
  • Weitersuchen: Ein gefundenes Synonym kann markiert und durch Aktivieren von Weitersuchen als neues Suchwort übernommen werden.
  • Kopieren: Nicht immer möchte man sich nur in der Anwendung aufhalten, sondern braucht das Wort vielleicht, weil man gerade einen Text schreibt. Das gefundene Synonym kann in die Zwischenablage kopiert und in der Zielanwendung wieder eingefügt werden.

Sag's anders bleibt nach wie vor eine kostenlose App. Sie kann im Marketplace heruntergeladen werden (Deeplink) - befindet sich die Anwendung im Hochformat wird lediglich am unteren Bildschirmrand ein kleines Werbebanner eingeblendet.

SQL Server 2012 und neue analytische Funktionen

05.01.2012 10:12:00 | Martin Hey

Dieser Post zum Thema Neuerungen im SQL Server 2012 widmet sich einigen neu hinzugekommenen analytischen Funktionen. Damit sind Auswertungen der Datenbestände möglich. Und ganz besonders zum Jahresende sind auch Performanceberichte und Vorjahresvergleiche immer von besonderer Bedeutung. Aus diesem Grund möchte ich mich heute etwas näher damit beschäftigen, wie man aktuelle Zahlen - seien es nun Verkaufszahlen, Umsatzzahlen, Gewinne, Arbeitslosenanzahl oder was auch immer mit anderen Zeiträumen vergleicht.

Der SQL Server 2012 bietet hier ein paar wesentliche Verbesserungen, dass sich der Datenbankentwickler nicht mehr zwingend die Finger brechen muss um mit Verrenkungen an diese Werte zu kommen. Mit Hilfe zweier neuer Funktionen und einer neuen Klausel sind Vorzeitraum- bzw. Folgezeitraumbetrachtungen oder Auswertungen mit einem gleitenden Fenster kein Problem mehr. Schauen wir uns das gemeinsam an einigen Beispielen an:

Werte vorangegangener Zeilen mit einfließen lassen (LAG)

Die Funktion LAG ermöglicht es, die vorhergehenden Zeilen mit in die Auswertung einfließen zu lassen. Das ging auch bisher schon, jedoch musste man dazu etwas kreativ sein, wie man an die letzten Datensätze vor dem eigentlich in der WHERE-Klausel definierten kommt. Häufig endete dies in einem Self-Join - mit entsprechend negativer Auswirkung auf den Ausführungsplan. LAG erlaubt nun, vorhergehende Zeilen mit zu berücksichtigen, ohne Self-Joins. Ein paar kurze Beispiele:

Gegeben ist eine Tabelle mit kumulierten Einkünften pro Geschäftsmonat.

 

Welche Auswertung ist nun für Controller interessant? Zunächst wäre doch spannend, wie der aktuelle Monat verglichen mit dem Vormonat - also 03/2012 verglichen mit 02/2012 - oder gar dem Vorjahresmonat - also 01/2012 verglichen mit 01/2011 abschneidet. Gar nicht so kompliziert dank der LAG-Funktion:

-- Vergleich Einkünfte aktueller Monat und Vormonat
SELECT Year, Month, Revenue CurrentRevenue,
LAG(Revenue, 1, 0) OVER (ORDER BY Year, Month) AS PreviousRevenue
FROM [dbo].[Revenues]

-- Vergleich Einkünfte aktueller Monat und Vorjahresmonat
SELECT Year, Month, Revenue CurrentRevenue,
LAG(Revenue, 12, 0) OVER (ORDER BY Year, Month) AS PreviousRevenue
FROM [dbo].[Revenues]

Am Beispiel sieht man schon, dass man der LAG-Funktion als Parameter den Offset angibt - also im Beispiel 1 oder 12 Zeilen - und im OVER noch definiert, in welcher Reihenfolge denn vorher sortiert werden soll. Der zweite Parameter definiert den Standardwert, der ausgegeben werden soll, wenn am angegebenen Offset kein Wert gefunden wurde.

 

Die nächste Auswertung, die häufig in solchen Zusammenhängen durchgeführt wird, sind Quartalsvergleiche - also: Wie schneidet das aktuelle Quartal verglichen mit dem Vorjahresquartal oder mit dem Vorquartal ab. Auch das ist recht unproblematisch, kann doch die LAG-Funktion auch mit Aggregatfunktionen umgehen.

-- Vergleich Einkünfte aktuelles Quartal und Vorquartal
SELECT Year, FLOOR((Month - 1) / 3) + 1 Quarter, Sum(Revenue) CurrentRevenue,
LAG(Sum(Revenue), 1, 0) OVER (ORDER BY Year, FLOOR((Month - 1) / 3) + 1) AS PreviousRevenue
FROM [dbo].[Revenues]
GROUP BY Year, FLOOR((Month -1) / 3) + 1

-- Vergleich Einkünfte aktuelles Quartal und Vorjahresquartal
SELECT Year, FLOOR((Month - 1) / 3) + 1 Quarter, Sum(Revenue) CurrentRevenue,
LAG(Sum(Revenue), 4, 0) OVER (ORDER BY Year, FLOOR((Month - 1) / 3) + 1) AS PreviousRevenue
FROM [dbo].[Revenues]
GROUP BY Year, FLOOR((Month -1) / 3) + 1

Das Ergebnis ist wieder recht vorhersagbar.

 

Werte kommender Zeilen mit einfließen lassen (LEAD)

Ähnlich wie LAG funktioniert LEAD. Unterschied hier: Während LAG vorhergehende Zeilen in die Betrachtung einfließen lässt, nimmt LEAD die folgenden Zeilen. Mit diesem Wissen sind nun Betrachtungen wie die im folgenden Beispiel möglich. Hier wird der Vorzeitraum, der aktuelle Zeitraum und der Folgezeitraum ausgewertet.

-- Vergleich Einkünfte aktueller Monat und Vormonat, Folgemonat
SELECT Year, Month, 
LAG(Revenue, 1, 0) OVER (ORDER BY Year, Month) AS PreviousRevenue,
Revenue CurrentRevenue,
LEAD(Revenue, 1, 0) OVER (ORDER BY Year, Month) AS NextRevenue
FROM [dbo].[Revenues]


-- Vergleich Einkünfte aktuelles Quartal und Vorquartal, Folgequartal
SELECT Year, FLOOR((Month - 1) / 3) + 1 Quarter, 
LAG(Sum(Revenue), 1, 0) OVER (ORDER BY Year, FLOOR((Month - 1) / 3) + 1) AS PreviousRevenue,
Sum(Revenue) CurrentRevenue,
LEAD(Sum(Revenue), 1, 0) OVER (ORDER BY Year, FLOOR((Month - 1) / 3) + 1) AS NextRevenue
FROM [dbo].[Revenues]
GROUP BY Year, FLOOR((Month -1) / 3) + 1

Auch hier ist das Ergebnis recht selbsterklärend.

 

Gleitende Ausschnitte mit OVER

In den bisherigen Beispielen war die Berechnung für die Zeiträume immer recht fix. Häufig wird bei Statistiken aber auch mit gleitenden Zeiträumen gearbeitet. Uns interessiert nun der gleitende 3-Monatsschnitt - heißt, wir können nicht mehr fix das Quartal berechnen, sondern müssen ein Zeitfenster bilden, das den aktuellen Monat, den Vormonat und den Folgemonat einschließt. Hier kann OVER weiterhelfen. SQL Server 2012 bringt auch hier Erweiterungen mit sich.

-- Vergleich Einkünfte aktueller Monat und gleitender Dreimonatsschnitt
SELECT Year, Month, 
Revenue CurrentRevenue,
AVG(Revenue) OVER (ORDER BY Year, Month ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) ThreeMonthsAvg
FROM [dbo].[Revenues]

Der gewünschte Betrachtungszeitraum in dem sich das Fenster bewegt kann mit Hilfe von ROWS BETWEEN angegeben werden.

 

Im Beispiel wird der aktuelle Monat und der gleitende Dreimonatsschnitt nebeneinander ausgewertet.

Wie schon eingangs beschrieben, können nun recht einfach und in vielen Fällen auch mit weniger Ausführungskosten (bezogen auf die Ressourcen des SQL Servers) Auswertungen durchgeführt werden, die zwar bisher auch schon möglich waren, aber oft nur mit komplexen Ausdrücken. Die neuen Funktionen erhöhen zudem die Lesbarkeit des SQL-Statements.

MS Office 2010 Objektmodell Veränderungen

05.01.2012 01:08:00 | Lars Keller

Continous Delivery per Dropbox

03.01.2012 14:45:00 | Jürgen Gutsch

Neulich hatten wir das Problem, dass wir sehr schnell eine ASP.NET MVC Anwendung auf einen Testserver bringen mussten. Die Lösung lag direkt vor der Nase:

  • Wir richteten auf dem Buildserver und den Testserver Dropbox ein.
  • Der Buildserver (in unserem Fall ist es Jenkins) baut (bei jeder Änderung im Source Code Management) die Anwendung und kopiert den Output das entsprechende Dropbox-Verzeichnis.
  • Dropbox synchronisiert nun die Files mit dem Testserver
  • Auf dem Testserver zeigt das Web im IIS direkt auf das entsprechende Dropbox-Verzeichnis und die Web-Anwendung kann direkt aufgerufen und getestet werden.

Nachteile:

  • Der User unter dem der Dropbox-Dienst läuft muss auf den Servern angemeldet bleiben.
  • Es kann zu Synchronisationkonflikten kommen, wen auf dem Testserver ebenfalls Files verändert werden.

Heinweis:

Continous Delivery über die DropBox sollte auf keinen Fall produktiv genutzt werden und ist allerhöchstens für die private Umgebung sinnvoll. Zum einen sind die oben genannten Nachteile recht störend, wenn man viel Änderungen macht, zum anderen ist Dropbox zwar ein hilfreiches Tool, aber nicht wirklich 100% vertrauenswürdig.

SQL Server 2012 und neue Datumsfunktionen

03.01.2012 14:40:00 | Martin Hey

Über KonvertierungsfunktionenFormatierungsmöglichkeiten und Logikfunktionen in SQL Server 2012 habe ich schon berichtet. Heute soll es um neue Datumsfunktionen gehen.

*FROMPARTS-Funktionen

Eine Möglichkeit Datums- und Zeitwerte zu erstellen ist, die Werte aus Textwerten zu parsen bzw. zu konvertieren  (z.B. mit PARSE oder mit CONVERT). Wenn der Wert nur als Text zur Verfügung steht, dann ist das durchaus ein akzeptabler Weg. In der Vergangenheit wurde dieser Weg jedoch auch häufig gewählt, wenn man Datumsteile vorliegen hatte. Oft wurde dann ein Text im passenden Format per Stringverkettung erstellt und dieser dann mit Hilfe von CONVERT in einen Datumswert konvertiert. Dieser Weg ist aber recht umständlich und fehleranfällig, da die Culture beim Format eine wesentliche Rolle spielt.

Neu im SQL Server 2012 ist sind nun Funktionen wie DATEFROMPARTS oder DATETIMEFROMPARTS, in der man Datumsfraktale angeben kann und hier typsicherer Datumswerte erzeugen kann.

DECLARE @year int, @month int, @day int;
SET @year = 2012;
SET @month = 1;
SET @day = 12;

-- alt
SELECT CONVERT(datetime, LTRIM(@day) + '.' + LTRIM(@month) + '.' + LTRIM(@year), 104)
-- neu
SELECT DATETIMEFROMPARTS(@year, @month, @day, 0, 0, 0, 0)

Genau wie DATETIMEFROMPARTS gibt es Funktionen für so ziemlich alle Datums- und Zeitdatentypen des SQL Servers.

EOMONTH 

Welches Datum hat der Monatsletzte? Besonders wenn man Zeitraumberechnungen oder Ultimoberechnungen durchführen möchte, spielt diese Frage eine relevante Rolle. Wie löst man dieses Problem bisher?

DECLARE @currentdate datetime = GETDATE();
SELECT DATEADD(dd,-DATEPART(dd,DATEADD(MM,1,@currentdate)),DATEADD(MM,1,@currentdate))

Man addiert einen Monat zum aktuellen Datum hinzu und zieht dann die Anzahl von Tagen ab, die im aktuellen Monat schon vergangen sind.

Damit man nicht mehr solche Verrenkungen machen muss, gibt es nun die Funktion EOMONTH, die den Monatsletzten des Monats ermittelt.

SELECT EOMONTH(GETDATE())

Wer mag, kann im zweiten Parameter noch einen zusätzlichen Offset hinzufügen, um so zum Beispiel den Monatsletzten des Folgemonats zu ermitteln.

Binär, XML und JSON vs. Custom-Serializer

03.01.2012 14:22:00 | Klaus Bock

binär code… oder; wenn du schnell sein willst musst du dich selbst darum kümmern.
Im vorherigen Artikel wurden bisher nur Standardserialiserer und ihre Formate miteinander verglichen. Die Ergebnisse waren schon recht ordentlich und die Erkenntnisse aus den Vergleichen sehr lehrreich. Vor allem der Vergleich XML vs. JSON animierte mich dazu, die gewonnenen Erkenntnisse weiter zu führen. Meines Erachtens nach, resultiert der Vorteil von JSON gegenüber XML in der deutlich schlankeren Definition der erzeugten Daten. Während XML vom Klassennamen über die Namen der Enthaltenen Eigenschaften bis zum Typ des Inhalts von Kollektionen alles schreibt, beschränkt sich JSON auf den Namen der Eigenschaften und ihren Inhalt. Wenn ich diesen Gedankengang konsequent weiterführe, kann ich in einem angepassten Serialisierer selbst auf die Namen der Eigenschaften verzichten und statt dessen mittels Indexer auf den jeweiligen Wert des serialisierten Objekts zugreifen.
Als nächste Konsequenz kann die komplette Typbehandlung beim De/Serialisieren entfallen, da der zu de/serialiserende Typ bekannt ist und nur dieser verwendet wird. Aber nun der Reihe nach.

Der Anlass für die Vergleiche der verschiedenen Serialisierer, war eine Anforderung aus einem aktuellen Projekt über das ich in diesem Artikel bereits geschrieben haben:
Eine Kollektion eines bekannten Typs in einem geschlossenen System schnell und effizient zu serialisieren und deserialisieren.
Solange ich einen der Standardserialisierer verwende, werde ich immer die Typbehandlung des jeweiligen Serialisierer in Kauf nehmen müssen, da der Serialisierer mit beinahe jedem gängigen .NET Objekt umgehen muss. Warum also nicht die Serialisierung auf das notwendige beschränken? Das Notwendige ist per Definition alleinig der Inhalt der öffentlichen Eigenschaften.

Wie könnte so eine serialisierte Zeichenfolge aussehen, die den Inhalt der öffentlichen Eigenschaften darstellt?
Da eine Kollektion serialisiert werden soll, muss als erstes zwischen den einzelnen Einträgen der Auflistung getrennt werden. Als nächstes muss eine Trennung zwischen den einzelnen Eigenschaften eines Eintrags her. Am einfachsten erschien mir ein Muster nach folgendem Beispiel:
[#|#|#…]
Die eckigen Klammern umschließen eine Klasse, also einen Eintrag in der Auflistung. Mit einem oder-Operator (|) wird zwischen den einzelnen Eigenschaften abgegrenzt. Zur Darstellung eines Array oder einer anderen Auflistung habe ich mich für folgendes Muster entschieden:
(n,n,n…)
Kombiniert ergibt sich für die Klasse TestNode, aus diesem Artikel, das endgültige Muster:
[#|#|#|(n,n,n…)]

Zum erzeugen der Zeichenfolge, habe ich mich für eine Überladung der ToString-Methode entschlossen, die eine Zeichenfolge als Format erwartet.

internal string ToString(string format)
{
    return string.Format(
        CultureInfo.InvariantCulture,
        "[{0}|{1}|{2}|({3})]",
        this.Name,
        this.MessagingUrl,
        this.Token,
        string.Join(
            ",",
            (this.Ranges
                .Select(i => i.ToString(CultureInfo.InvariantCulture)))
                .ToArray()));
}

Für diesen Benchmark wird der Parameter format noch nicht ausgewertet. Später könnten hier Werte wie etwa “C” für Custom oder “J” für JSON angegeben und entsprechend verarbeitet werden.

Die eigentliche Serialisierung in einem CustomFormatter ist eher trivial. Es wird lediglich die Auflistung durchlaufen, für jedes Element die überladene ToString(string)-Methode aufgerufen und die zurückgegebene Zeichenfolge in einen StreamWriter geschrieben.

public void Serialize(HttpResponse response, List<TestNode> data)
{
    response.ContentType = "application/json";
    using (var writer = new StreamWriter(response.OutputStream))
    {
        foreach (var entry in data)
        {
            writer.Write(entry.ToString(null));
        }
    }
}

Die Deserialisierung ist ähnlich einfach. Der empfangene Stream wird in einen StreamReader gelesen und die enthaltene Zeichenfolge, dem vorher beschriebenen Muster entsprechend, aufgeteilt und die erzeugten Fragmente jeweils einer neuen Instanz der Klasse TestNode bzw. den Eigenschaften zugewiesen.

public List<TestNode> Deserialize(Stream responseStream)
{
    var list = new List<TestNode>();
    var rawSeparator = new char[] { '[', ']' };
    var propertySeparator = new char[] { '|' };
    var rangeSeparator = new char[] { '(', ')', ',' };
    using (var reader = new StreamReader(responseStream))
    {
        var rawData = reader.ReadToEnd()
            .Split(rawSeparator, StringSplitOptions.RemoveEmptyEntries);
        foreach (var entry in rawData)
        {
            var properties = entry.Split(
                propertySeparator,
                StringSplitOptions.RemoveEmptyEntries);
            if (properties.Length < 1)
            {
                continue;
            }
            var ranges = properties[3]
                .Split(rangeSeparator, StringSplitOptions.RemoveEmptyEntries)
                .Select(s => int.Parse(s, CultureInfo.InvariantCulture));
            var node = new TestNode
            {
                Name = properties[0],
                MessagingUrl = properties[1],
                Token = properties[2],
                Ranges = new List<int>(ranges)
            };
            list.Add(node);
        }
    }
    return list;
}

Die Erzeugung der temporären Variablen ranges, ist nur der Übersicht halber im Code enthalten. Das Aufteilen und parsen der Zeichenfolge kann auch im Konstruktor von List<T> für die Eigenschaft Ranges erfolgen.

Nach dem die Methodik stand wollte ich natürlich wissen, ob auch der erwartete Effekt eintrat bzw. eine verbesserte Leitung gegenüber den bisher verwendeten Serialisierern messbar ist.

Der Benchmark wurde um die Messung der Deserialisierung erweitert. So kann ein besseres Gesamtbild des jeweiligen Serialisierers wiedergegeben werden.
Die Werte der Spalten Response, Deseria. und Complete sind jeweils in Millisekunden dargestellt. Count gibt die Anzahl der Elemente in der übertragenen Auflistung wieder und Transfered die Anzahl der übertragenen Bytes.

Ich habe kurzerhand die beschriebene Methodik als CustomFormatter mit dem Kürzel custom dem Benchmark hinzugefügt und dieses laufen lassen.
Was soll ich sagen; die Zahlen sprechen für sich.

Format Count Comp Response Deseria. Complete Transfered
bin 1
1
gzip 1
1
1
1
968
559
xml 1
1
gzip 1   1 423
364
jsondata 1
1
gzip 1   1 219
269
jsonweb 1
1
gzip 2   2 148
246
jsonnet 1
1
gzip 2
5
  2
5
148
246
custom 1
1
gzip
1
 
1
101
209
Format Count Comp Response Deseria. Complete Transfered
bin 10
10
gzip 1
1
  1
1
2.581
1.372
xml 10
10
gzip 4
1
1 1 3.494
947
jsondata 10
10
gzip 1
1
  1 2.300
813
jsonweb 10
10
gzip 1
1
  2 1.590
773
jsonnet 10
10
gzip 2 1
1
3
1
1.590
773
custom 10
10
gzip 2   2 1.129
723
Format Count Comp Response Deseria. Complete Transfered
bin 100
100
gzip 3
2
29
2
32
4
18.611
8.831
xml 100
100
gzip 1
2
1
1
2
3
33.649
6.312
jsondata 100
100
gzip 1
1
2
3
3
4
23.005
5.713
jsonweb 100
100
gzip 1
2
6
6
7
8
15.905
5.397
jsonnet 100
100
gzip 1
1
2
2
3
3
15.905
5.397
custom 100
100
gzip
1
1
1
1
2
11.304
5.125
Format Count Comp Response Deseria. Complete Transfered
bin 1.000
1.000
gzip 11
20
42
26
53
46
177.927
80.243
xml 1.000
1.000
gzip 5
15
8
10
13
25
329.784
59.224
jsondata 1.000
1.000
gzip 6
13
23
26
29
39
229.068
53.906
jsonweb 1.000
1.000
gzip 11
18
61
65
72
83
158.068
50.626
jsonnet 1.000
1.000
gzip 5
11
19
21
24
32
158.068
50.626
custom 1.000
1.000
gzip 2
8
7
5
9
13
112.067
47.624
Format Count Comp Response Deseria. Complete Transfered
bin 10.000
10.000
gzip 125
210
528
215
653
425
1.770.091
793.997
xml 10.000
10.000
gzip 47
148
114
114
161
262
3.284.950
587.571
jsondata 10.000
10.000
gzip 53
143
377
267
430
410
2.287.996
535.119
jsonweb 10.000
10.000
gzip 113
177
651
711
764
888
1.577.996
502.584
jsonnet 10.000
10.000
gzip 47
112
211
254
258
366
1.577.996
502.584
custom 10.000
10.000
gzip 27
77
48
72
75
149
1.117.995
472.300
Format Count Comp Response Deseria. Complete Transfered
bin 100.000
100.000
gzip 1.389
2.255
11.064
8.115
12.453
10.370
17.701.551
7.887.661
xml 100.000
100.000
gzip 457
1.424
916
1.161
1.373
2.585
32.890.892
5.876.977
jsondata 100.000
100.000
gzip 523
1.300
2.594
2.772
3.117
4.072
22.887.368
5.349.086
jsonweb 100.000
100.000
gzip 1.116
1.781
6.676
6.692
7.792
8.743
15.787.368
5.023.391
jsonnet 100.000
100.000
gzip 462
1.163
2.124
2.261
2.568
3.424
15.787.368
5.023.391
custom 100.000
100.000
gzip 221
842
518
761
739
1.603
11.187.367
4.721.865

Wie obige Zahlen zeigen, schlägt die kleinere Datenmenge sofort zu Buche. Das Fehlen jeglicher Typbehandlung ist in der Responsetime und der sehr kurzen Zeit für die Deserialisierung ebenfalls deutlich zu sehen.

Die vorgestellte Methodik ist beileibe noch kein Produktivcode. Sie soll lediglich zeigen, dass auch einfache Ansätze zu guten Ergebnissen führen können.

Der Beispielcode ist als Projekt SerializeTesting bei Bitbucket gehostet. Erweiterungen um eigene Ideen sind ausdrücklich erwünscht.

Fazit:

Es muss nicht immer ein Serialisierer mit der kompletten Funktionalität verwendet werden.
Wie bereits der Vergleich der gängigen Serialisierer untereinander gezeigt hat, kostet Overhead einfach Zeit. Ob nun das erzeugte Format oder die interne Verarbeitung der zu de/serialisierenden Objekte spielt dabei keine Rolle. Wenn konsequent auf jeglichen Overhead verzichtet wird, ist das daraus resultierende Ergebnis immer schlank und effizient. Wie weit die Entschlackung getrieben wird, ist jedem selbst überlassen.

Technorati-Tags: | | | | |

Ein Blick auf das Entity Framework 4

03.01.2012 14:18:00 | Jürgen Gutsch

Angeregt durch ein aktuelles Projekt, musste ich mir das Entity Framework 4 (Microsofts OR-Mapper) anschauen. Bisher hatte ich es vermieden, da ich der Meinung war, dass ich die nötigen Mappings nur über den Designer mit viel Magie und wildem herumgeklicke herstellen kann. Allerdings halte ich es für wichtig, dass die Entities, die ich in meinen Projekten benötige, nicht autogeneriert sind, bzw. nicht vom OR-Mapper generiert werden, da dadurch unnötige Abhängigkeiten zum OR-Mapper entstehen oder unnötige Objekt-Mappings gemacht werden müssen.

Üblicherweise halte ich meine Entities in einem Projekt, das von allen anderen Projekten referenziert wird, die mit diesen Entities arbeiten. Mit NHibernate ist das auch problemlos möglich.

BTW: Ich bin ein großer Fan von NHibernate und nutze diesen OR-Mapper bisher in fast jedem großen Projekt.

Ich möchte also meine Entities wie folgt aufbauen:

public class Customer : EntityBase
{
    [StringLength(150)]
    [Required]
    public string Name { get; set; }
    [StringLength(100)]
    [Required]
    public string Street { get; set; }
   
    [StringLength(5)]
    [Required]
    [RegularExpression("^[0-9]{4,5}$")]
    public string Postalcode { get; set; }
}

EntityBase ist eine Basisklasse, welche die Id bereitstellt, Equals überschreibt, etc. Die hier sichtbaren Attribute stammen von den DataAnnotations und werden zur Validierung genutzt.

Würde ich jetzt das EF wie gewohnt einsetzen, müsste ich z. B. per AutoMapper von den generierten Entities auf meine Mappen. Das möchte ich nicht, bzw. müsste es mit NHibernate auch nicht tun.

DbContext

Nun war es heute René Leupold der mir mit seinem Blog http://databinding.net den entscheidenden Tipp für den DbContext gab. Mit dem DbContext ist es möglich das Entity Framework ähnlich wie NHibernate zu verwenden.

Hilfreich ist auch die Artikelserie “Using DbContext in EF 4.1” im ADO.NET Team Blog

Der DbContext ist ab EF 4.1 verfügbar. Ich selber habe mir für diese Beispiele die EntityFramework.dll 4.2.0.0 per NuGet referenziert.

Das Mapping

Was wir zusätzlich benötigen ist ein Mapping, das hier per Fluent API per C# gesetzt wird:

internal class CustomerMapping : EntityTypeConfiguration<Customer>
{
    public CustomerMapping()
    {
        Property(x => x.Name)
            .HasMaxLength(200)
            .IsVariableLength()
            .IsUnicode()
            .IsOptional();
        Property(x => x.Postalcode)
            .HasMaxLength(30)
            .IsVariableLength()
            .IsUnicode()
            .IsOptional();
    }
}

Genutzt wird die Konfiguration dann im DbContext:

public class DataContext : DbContext
{
    public IDbSet<Customer> Customers { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Configurations.Add(new CustomerConfig());
    }
}

Die Ähnlichkeit mit NHibernate ist an dieser Stelle eindeutig und ich habe meine gewünschte Trennung zwischen den Entities und dem OR-Mapper.

Die Connection

Interessant ist, dass die Verbindung zur Datenbank über den Constructor der Basisklasse DbContext gesetzt werden kann oder aber per Konvention:

<connectionStrings>
    <add name="DataContext"
         providerName="System.Data.SqlClient"
         connectionString="Data Source=[…]" />    
</connectionStrings>

Der Name des ConnectionStrings muss einfach so heißen wie der entsprechende DbContext

Benutzen

Wenn die DB schon existiert ist das im Prinzip auch schon alles um mit den Daten zu arbeiten:

[Test]
public void SetAndLoadCustomerFromDataBase()
{
    IEnumerable<Customer> customers;
    using (var context = new DataContext())
    {
        context.Customers.Add(new Customer
                                  {
                                      Id = Guid.NewGuid(),
                                      Name = "Hallo Welt",
                                      Street = "Hallo Street 2",
                                      Postalcode = "12345"
                                  });
        context.SaveChanges();
    }
    using (var context = new DataContext())
    {
        customers = context.Customers.Select(c => c).ToList();
    }
    Assert.That(customers.Count(), Is.GreaterThan(0));
}

Das Mapping wird erzeugt, wenn das erste mal der DataContext instanziert wird. Es wird relativ viel mit Lazy<T> gearbeitet, so dass das Debugging der ergebnislisten nicht immer ganz einfach ist.

 

Demo

Eine Demo werde ich in den nächsten Tagen hier anhängen. Die vorhandenen Projekte muss ich erst noch anonymisieren.

Fazit

Mit dem DbContext scheint das EntityFramework doch noch ein ganz passables Werkzeug und eine ernstzunehmende Alternative zum NHibernate zu sein.

Password Protect a single aspx page

02.01.2012 17:38:00 | Andreas Mehl

 

In IIS 7 you can either password protect a folder or password protect a specific page. When you password protect a folder all the files or objects within that folder will be password protected. However there maybe some instances where you do not want to password protect the entire content of that folder but merely a single page. To achieve this simply follow these steps.

 

    1. Connect to the web server using IIS 7 Manager.

    2. Click on “Content View “at the bottom of the IIS 7 Manager and navigate to the file you want to password protect.

    3. Right click on the target file and choose “Switch to Features View”.

    4. Double click on Authorization Rules.

    5. Click “Add Deny Rule”.

    6. In the pop up dialogue box, select “All anonymous users”.

    7. Click “OK”.

 

The web.config will now have this element inputted into it. Bear in mind that you do not have to go through IIS 7 Manager to achieve this. You can directly go to your applications web.config file and input the proper elements and properties to password protect a specific page.

 

<location path="file1.aspx">
        <system.webServer>
            <security>
                <authorization>
                    <add accessType="Deny" users="?" />
                </authorization>
            </security>
        </system.webServer>
    </location>

SQL Server 2012 und neue Konvertierungsfuktionen

02.01.2012 13:50:00 | Martin Hey

Mit SQL Server 2012 kommen auch neue Konvertierungsmöglichkeiten hinzu. Bisher bekannt sind ja schon die Möglichkeiten CAST und CONVERT.

TRY_CONVERT

CONVERT führt zu einem Fehler, wenn die Konvertierung nicht funktioniert. Kleines Beispiel gefällig?

SELECT ISNUMERIC('1e1')
SELECT CONVERT(int, '1e1')

Obwohl ISNUMERIC den Wert 1 zurückliefert, schlägt der Aufruf von CONVERT fehl. Eine Konvertierung in den float-Datentyp hingegen wäre erfolgreich. Hier hilft TRY_CONVERT.

SELECT TRY_CONVERT(int, '100')
SELECT TRY_CONVERT(int, '1e1')

Diese Funktion gibt NULL zurück, wenn die Konvertierung nicht durchgeführt werden kann, oder im Erfolgsfall eben den Wert.

PARSE und TRY_PARSE

Um Datums- oder Zahlenwerte aus einem Text in die jeweiligen Datentypen zu konvertieren gibt es nun die Funktionen PARSE und TRY_PARSE. Unterschied zwischen beiden Funktionen ist - ähnlich wie bei CONVERT und TRY_CONVERT auch, dass PARSE eine Exception wirft, wenn die Konvertierung nicht durchgeführt werden kann, TRY_PARSE hingegen NULL.

SELECT TRY_PARSE('01.02.2012' AS datetime USING 'de-DE')
SELECT PARSE('01.02.2012' AS datetime USING 'en-US')
SELECT PARSE('1234567' AS datetime USING 'en-US')
SELECT TRY_PARSE('1234567' AS datetime USING 'en-US')

Wird keine Culture angegeben, so verwendet PARSE die Culture, die mit Hilfe von SET LANGUAGE gesetzt wurde. Sowohl PARSE als auch TRY_PARSE basieren auf der CLR, was zur Folge hat, dass alle Cultures angegeben werden können, die die CLR kennt - nicht nur jene, die dem SQL Server bekannt sind.

Regeln | Impressum