.
Anmeldung | Registrieren | Hilfe

.NET-Blogs Archiv Mai 2008

Microsoft Source Analysis for C#

31.05.2008 14:59:00 | Klaus Bock

Mit Microsoft Source Analysis for C#, aka StyleCop, wurde ein weiteres Werkzeug zur Codeanalyse freigegeben. Im Gegensatz zu FxCop, der den IL-Code analysiert, untersucht Source Analysis den Quellcode. Das Tool wird als VS-AddIn oder während des Build-Vorgangs verwendet. Da ich nur die C# Express Version besitze, kam für mich nur die Verwendung im Build-Prozess in Frage. Wie Source Analysis in den Build-Prozess eingebunden wird, ist sehr ausführlich in diesem Blog Artikel beschrieben. An das UI von Source Analysis kommt man in der Express Edition nicht so schön heran wie in Visual Studio Standard oder Professional. Aber dafür gibt es in den Express Editions unter Extras den Menüpunkt Externe Tools. Hier kann nun die SourceAnalysisSettingsEditor.exe mit der Einstellungsdatei Settings.SourceAnalysis als Parameter eingetragen werden. Hier ein ScreenShot wie der Menüeintrag aussehen sollte.

Externe Tools SourceAnalysis Da ich nicht für jedes Projekt neue Einstellungen benötige, verwende ich nur die Einstellungen der Datei im Installationsordner von Source Analysis. Für Leute die in ihren Projekten unterschiedliche Einstellungen benötigen, kann hier mit den Argumenten, etwa dem Projektverzeichnis, von C# Express gearbeitet werden.

Nach dem der Menüpunkt jetzt zur Verfügung steht, können die Einstellungen von Source Analysis den eigenen Anforderungen angepasst werden. Ich kann allen die ihre Kommentare in deutsch ausführen nur empfehlen die Regel SA1623 zu deaktivieren. Diese Regel prüft den Kommentar von Eigenschaften ob dieser, je nach Accessor, mit Get's oder Set's beginnt. Macht ja im deutschen wenig Sinn.

Wer eigene Regeln verwenden will findet in diesem Blog eine recht ausführliche Anleitung um Bibliotheken mit eigenen Regeln für Source Analysis zu erstellen.

Nach dem Source Analysis das erste mal über eine Bibliothek gelaufen war, bekam ich große Augen. Ich dachte immer ich würde mich an die Entwurfsrichtlinien halten. Aber über 500 Warnungen sagen etwas anderes aus. Gut, zum größten Teil waren es Meldungen der Regel SA1027: Tabs are not allowed. Use spaces instead. Was Source Analysis auch gar nicht gefällt, sind private Felder die mit einem "_" beginnen. Auch die Regel SA1201: All properties must be placed after all constructors. wurde oft angezeigt. Bisher habe ich immer wie folgt strukturiert: private Felder, Eigenschaften, Konstruktoren, öffentliche Methoden und zum Schluss die privaten Methoden. War anscheinend falsch.

Für einzelne Personen wie mich ist es relativ einfach den Stiel zu ändern. Aber was ist mit großen Teams? Wer Interesse hat, kann sich einmal die Diskussionen zu Source Analysis zu Gemüte führen.

 

Technorati-Tags: |

Unbeschwertes Debugging von WebApps und Breakpoint Condition

31.05.2008 12:45:00 | Peter Bucher

Auf einen Request warten / Nicht an eine Browserinstanz gebunden

Standardmässig ist unter den Web-Einstellungen in den Projekt-Einstellungen jeweils die per Visual Studio markierte Applikation + ggf. eine Startseite markiert.

Beim Starten des Debugging geht ein neues Fenster auf, und bei einem Breakpoint meldet sich VS wieder.

Soweit alles bekannt und nicht mal so schlecht. Allerdings ist die gestartete Browser Instanz direkt mit dem derzeitigen Debugging verkettet und beim Schliessen der Browserinstanz bricht das Debugging im Visual Studio ab.

Eine weitaus komfortablere Lösung ist folgendes:

weitforarequest

Zu finden über: Rechtsklick auf die WebApp -> Eigenschaften -> Web

Mit dieser Einstellung kann das Debugging gestartet werden, ohne dass direkt an eine Browserinstanz gebunden wird.
Wenn dann seperat irgend ein Browser oä. einen Request an die aktive Adresse sendet, wird das Debugging aktiv.

So geht nicht immer ein neues Fenster auf, das Debugging läuft durch (Nicht nur ein Request + immer wieder Neustarten) und es können bspw. (obwohl das IMHO kein Sinn macht) mehrere Browserinstanzen verschiedener Typen gleichzeitig invoviert sein.

Eine ganz nette Sache und die Geschichte funktioniert sowohl mit dem integrierten Webserver, wie auch mit einem IIS.

Jürgen setzt das auch schon längere Zeit ein und fährt gut damit.

Breakpoint Condition

Breakpoints kennen wir ja alle, eine Breakpoint Condition ist eine Einschränkung - sodass der Debugger nur bei Erfüllung einer Kondition anhält.

Beispiel aus der Praxis:
Ein Datengebundenes Control ist mehrfach auf einer Seite vorhanden, das muss auch so sein.
Jedoch verhält sich das Control in einem Fall nicht so wie es sollte, evt. sogar im Zusammenhang mit den anderen Contorlinstanzen.

Beim Debuggen hänge ich mich in die Methode "PerformDataBinding" ein, möchte jedoch nur dann hängen bleiben, wenn ich tatsächlich bei meinem gewünschten Control bin.

Nichts leichter als das - einfach ein Breakpoint anlegen, anschliessend ein Rechtsklick darauf und auf "Condition" klicken.
Im folgenden Fenster kann - sogar mithilfe von Intellisense - direkt eine Kondition im aktuellen Kontext gestellt werden.

In diesem Beispiel überprüfe ich per this.ID == "meinControl", ob das gewünschte Control erreicht ist. Wenn wahr hält der Debugger dort an.

breakpointcondition 

Möglich ist sowas auch in Handarbeit per System.Diagnostics.Debugger-Klasse.
Beispiel (Macht schlussendlich das selbe wie oben):

if (this.ID == "meinControl")
    Debugger.Break();

 

Viel Spass beim Debuggen!

Mit UI Automation Web Anwendungen testen

29.05.2008 15:51:37 | Christian Binder

Gestern hatte ich einen Vortrag zum Thema Rosario bei der .Net User Group in Ulm. Ein Demo war die UI Automatisierung einer Web Application vom Manual-test zum automatisierten Unit Test, Thomas hat die Idee gleich mal aufgenommen und das Ganze mit dem UI Automation Framework getestet, zu dem wir schon mal ein Webcast gemacht haben. Natürlich gibt es noch keinen Recorder, aber Hier findet Ihr das Ergebnis :-)

Viel Spass

Chris

System.Drawing.Color von Html / Win32 / Ole und zurück

28.05.2008 20:24:00 | Peter Bucher

Wenn ein Farbwert als System.Drawing.Color Objekt vorliegt und ein Stringwert (Name oder Hex.) für die Html-Ausgabe benötigt wird, gibt es eine einfache Lösung dafür.
Die Klasse System.Drawing.ColorTranslator bietet einige statische Methoden an, die eine einfache und saubere Übersetzung ermöglichen (Auch Win32- oder Ole-Farbwerte).

Darin ist auch die Methode FromHtml enthalten, womit es eine bessere Möglichkeit gibt, als mein Hilfsmethode.
Nach einem schnellen Blick, wird da intern auch nicht der WebColorConverter benutzt, so stelle ich mir die Frage: Wieso zwei Klassen die das selbe anbieten?

Via C#-Farben in HTML-Farben umwandeln

Artikel: StyleSwitcher selbst gemacht

28.05.2008 19:15:18 | Peter Bucher

asp0208-cover-300px

In der aktuellen ASP.NET Professional 05/2008 Ausgabe  findet sich ein Artikel von mir über das StyleSwitcher-Control.
Im Artikel finden sich Informationen über das Innere des Controls, die Überlegungen dazu und die Implementation wird Schritt für Schritt erklärt.

Wer kein Abonnement von ASP.NET Professional besitzt, trotzdem mal reinschnuppern möchte und meinen Artikel interessant findet, kann sich ein kostenloses Probeabo zukommen lassen (Dort ist der aktuelle Artikel drin).

Steve & Bill…

28.05.2008 07:18:20 | Robert Mühsig

Herrlich was man auf YouTube für alte Microsoft Werbung findet:

Ein paar weitere Videos gibts auf Microsoft Watch - oder YouTube ;)

ASP.NET MVC Preview 3 released

28.05.2008 00:02:40 | Robert Mühsig

Das ASP.NET Team (siehe Scotts Blog) hat die 3. Preview des MVC Modells zum Downloaden freigegeben:

Die 3. Preview knüpft an den Code Release im April an und bringt eine ganze Reihe Verbesserung:

  • Control Action Methods & ActionResults z.B. für…
    • AJAX: JsonResult
    • Streaming Data: ContentResult
    • Web: HttpRedirect / RedirectToAction/Route
    • Dies ermöglicht sehr elegantes Unit-Testen
  • HTML Helper wurden verbessert
  • URL Routing & Mapping wurde erweitert (und ist nun Teil des .NET 3.5 SP1 für WebForms und MVC)

Was leider noch nicht enthalten ist, sind Sub-Controller, bessere AJAX Integration, Authentication, Authorization, Components - dies soll in späteren Releases nachgeschoben werden (Achtung: Zum Teil geht es hier auch um eine nettere Integration - Logingeschichten können sehr wohl mit dem MVC Framework gemacht werden.).

Weitere Infos einfach bei Scott nachschauen

Back in Black - Me too

27.05.2008 18:52:20 | Peter Bucher

VS08_h_rgb_r

Nachdem viele andere zur schwarzen Seite gewechselt sind, musste ich das auch mal probieren.

Seit Mitte April habe ich ein schwarzes Farb-Theme für Visual Studio eingestellt (Wink an Albert :).
Am Anfang ist die Benutzung etwas komisch und es braucht eine gewisse Gewöhnung.

Nach dieser Zeit muss ich sagen, dass es mir in schwarz besser gefällt :-)

backInBlack

Probiert es einfach selber mal aus.

PS: Im Forum bitte nicht schwarz Posten :))

Neu in TFS mit dem VS2008 Sp1 Beta

27.05.2008 16:53:05 | Christian Binder

Ich wurde nun doch des öfteren gefragt, was alles neu sein wird mit VS2008 Sp1.

  • Support for Windows Server 2008.
  • Support for SQL Server Codename Katmai CTP6.
  • The Add to Source Control dialogs have been improved to be easier to use and more scalable.
  • Drag & Drop from Windows Explorer to add to Source Control.
  • Support for Version control operations on files not in bound solutions.
  • Right-click access to set Working Folder/Cloak of folders from within Source Control Explorer.
  • Check in date/time column in Source Control Explorer.
  • Editable path field for the Source Control Explorer.
  • Email work items and queries to someone.
  • A new API to download files to a stream.
  • Links to Team System Web Access pages from notifications.
  • Improvements to the number of projects per server.
  • Performance and scale improvements.
  • Improvements to the VSS converter to make it much more robust.
  • Support for creating Team Projects from the command line.

Die Beta Version  ist schon verfügbar von TFS Sp1 und ist hier zu bekommen.

Viel Spass
Chris

Videos: das neue C++ Feature Pack und VSTS für native C++ Developer

27.05.2008 13:50:24 | Christian Binder

Boris Jabes aus dem C++ Product Team war zu Besuch in Bad Homburg und hat das neue C++ Feature Pack vorgestellt. Wir haben das wichtigste für Euch aufgenommen :-) und kleinere Videos zerteilt.

C++ what is new with Visual Studio 2008  : Vista Development and Security
Was ist neu in VS 2008 für C++ Entwickler? Fokus liegt hier for allem auf Vista Development und Security Features wie UAC.

video

C++ what is new with Visual Studio 2008 :  Build and Marshaling Features
Was ist neu in VS 2008 für C++ Entwickler? Fokus liegt hier auf Productivity Features wie den neuen Build- und Marshaling Features

video

Building Modern User Interfaces with the new MFC 
Die neuen MFC Features aus dem Feature Pack im Überblick. Oder wie Ihr Eurer MFC Applikation mit geringem Aufwand ein modernen Look geben könnt.

video

TR1 in Visual Studio 2008 and beyond
Was im TR1 Standard drin? Shared_ptr, weak_ptr, regex, mem_fn(),bind(), function, tuple, array, ......... 

video

The next C++ Generation: C++0x
Ein Blick in die Zukunft: C++0x

video

 

Die Präsentationen gibt's hier:

Building Modern UI with the new MFC

TR1 in VC 2008 and beyond

 

Dann hab ich mit Boris gleich noch zwei Videos zum Thema VSTS für native C++ Entwickler aufgenommen. Dabei haben wir folgende Features beleuchtet:

VSTS Profiler for native C++ Developer
Video, Demo Solution hier

VSTS Static and Dynamic Code Analysis for native C++ Developer
Video, Demo Solution hier

Viel Spass

Chris

Wöchentliche Rundablage: ASP.NET MVC, Silverlight 2, C#, Entity Framework, WPF, Javascript

26.05.2008 22:29:49 | Robert Mühsig

ASP.NET MVC:

ASP.NET:

ADO.NET Entity Framework:

Source Analysis for C#:

Architektur / Design:

Silverlight 2:

WPF:

Tipp / C#:

Design / CSS / Javascript:

Verschiedenes:

Extra-Session auf der Webinale - Kostenloses von Microsoft

26.05.2008 17:19:12 | Oliver Scheer

Diese Session gibt eine Übersicht über kostenlose Tools, Services und Komponenten von Microsoft für professionelle und semiprofessionelle Webentwickler. Von der Programmier-IDE, über das Webdesigntool bis hin zur Datenbank bietet Microsoft viele kostenlose Lösungen an. Neben den Basistools der Webentwicklung werden auch Enterprise-fähige Komponenten und Technologien vorgestellt, die es erlauben von kleinen Homepages bis hin zu Portalen alles zu bauen, was das Webentwickler- und Webdesignerherz begehrt – ohne Software-Lizenzkosten.

Mehr Infos: http://entwickler.com/konferenzen/planer/show_details.php?konferenzid=61&sessionid=8494

Sonntag 2.0

26.05.2008 12:45:00 | Lori Grosland

Gestern war Sonntag 2.0 in München, ein Mini-BarCamp zu Themen Web 2.0 und Sicherheitsaspekte.  Es war Microsoft Deutschlands erstes Mal, ein BarCamp ähnliches Event zu veranstalten. 

 

Obwohl es eine sehr kleine Runde war, war das Gespräch interessant.  Ich habe zumindest etwas neues zum Thema Sicherheit gelernt. :-)

 

In der Zukunft werden wir versuchen, ähnliche Events zu veranstalten. Aber nächstes mit ein bisschen mehr Anlaufzeit. Ich glaube 2 Wochen Anlaufzeit war wahrscheinlich zu wenig.

 

Weil das Event kurzfristig geplant war, wussten wir nicht wie viele Leute kommen würden.  Wir haben deswegen ein bisschen zu viel Essen bestellt und was übrig war, haben wir an der Bahnhofsmission gespendet.  Ich denke die Leute da haben sich darüber gefreut.  :-)

 

Hier sind ein paar Foto-Impressionen von Sonntag 2.0…

 

CIMG0317 CIMG0318  CIMG0319 IMAGE_170

Ze Germans - In die Mongolei und Zurück

25.05.2008 20:10:00 | Lori Grosland

Martin Saternus hat so viel Spaß mit unserem englischen Gespräch über Mongol Rally, dass er unbedingt ein zweites Mal befragt werden wollte - aber das zweite Mal auf Deutsch.  Ok, vielleicht habe ich ihn gezwungen.  ;-)  Aber es hat einfach Spaß gemacht, mit Richard und Martin darüber zu reden.  Ich glaube es war immer mein Traum  sowas ähnliches zu machen.  Mal gucken, ob ich es je schaffe. 

Hier ist das deutsche Interview mit Martin über Mongol Rally 2007, die Highlights und sein Lieblings-Fotos.  Mehr Info und Highlights von der Abendteuer und der Reise, findet Ihr auf ihrem Blog:

http://www.mongolrally.de/

Geeks in a Crap Car - Mongol Rally -> Photos & More

25.05.2008 19:25:00 | Lori Grosland

Last year in May I spoke with Martin Saternus at the STC in Duisburg about the Mongol Rally and he showed me the car that he and Richard Süselbeck would be driving from London to Ulan Bator.  Martin was at the STC to raise money for two charities, so they would be able to participate in the rally.  Students were given the opportunity to donate a little money to help the team out and in return they were able to sign their names on the rally car. 

I traveled back to Duisburg late last year to get the scoop from Martin about the adventure and to find out if the car and signatures made it to Ulan Bator.  Martin filled me in on his highlights from the trip and showed me some of his souvenirs and favorite photos from the trip.

Check out their blog for more highlights from the trip:

http://www.mongolrally.de/

ASP.NET 3.5 Extensions Preview

24.05.2008 23:14:00 | Ozgur Aytekin

Die neuen Features der Version ASP.NET 3.5 Service Pack 1 Beta werden auf der folgende Seite mit Videos vorgestellt:

ASP.NET Dynamic Data: ASP.NET Dynamic Data helps you quickly build a fully customizable, data-driven application without writing code. Dynamic Data provides a rich scaffolding framework that is easily extensible by using the traditional ASP.NET programming model.

ASP.NET AJAX browser history: ASP.NET AJAX history provides support for navigating within an AJAX application by using the Forward and Back buttons in the browser.

ASP.NET AJAX script combining: The ASP.NET AJAX script combining feature improves the performance of AJAX applications by reducing the number of scripts that have to be individually downloaded to the browser.

ADO.NET Data Services: ADO.NET Data Services provide new services that find, manipulate and deliver data over the web using simple URIs. Benefits include an easy and flexible way to access data over the web, while enabling the separation of presentation and data access code.

ADO.NET Entity Framework: ADO.NET Entity Framework is a new modeling framework that enables developers to define a conceptual model of a database schema that closely aligns to a real world view of the information. Benefits include easier to understand and easier to maintain application code that is shielded from underlying database schema changes.

Die URL: ASP.NET 3.5 Extensions Preview

ADO.NET Entity Framework - How Do I - Videos

24.05.2008 20:02:00 | Ozgur Aytekin

ADO.NET Team hat auf ihrem Blog mehrere Videos zum Thema ADO.NET Entity Framework veröffentlicht.

Für eine Einführung in das Thema Entity Framework kann euch diese Videos emfehlen:

How Do I Get Started with the Entity Framework?

How Do I Use the new Entity Data Source?

How Do I Serialize a Graph with the Entity Framework?

How do I use Entity Client?

Viel Spass...

Silverlight String.Format Tool

24.05.2008 19:40:00 | Ozgur Aytekin

Mit Silverlight implementiertes String.Format Tool "String.Format" kann vielen Entwicklern helfen, die verschiedenen Möglichkeiten der String-Formatierungen direkt Online auszuprobieren.

Silverlight_String_Format_Tool

Das Tool findet ihr unter: String Format - Made Simple

Geeks in a Crap Car - Mongol Rally -> They made it!

24.05.2008 15:10:00 | Lori Grosland

Whatever happened to those two German PhD Computer Science students that took part in the Mongol Rally 2007?!  Just as a reminder, the Mongol Rally is a charity event where participants drive from London to Ulan Bator in Mongolia in a crap car without a GPS or a navigation system.  Well...

They made it!  And in one piece!

Late last year I visited with both Martin Saternus and Richard Süselbeck to find out how the Mongol Rally 2007 went.  In this video, I chat with Richard about their experience during the trip, how much money they were able to donate to charities and of course their plans for the future. 

Check out their blog for more highlights from the trip:

http://www.mongolrally.de/

 

NOTE:  Why is this video coming so late, you may ask?  Well, some of you may remember that I had a small audio problem with some of my videos around the November and December timeframe.  Ok, if you have watched some of my videos from Innovation Day in Brussels then you know that it was more than a small problem.  Let’s just say that whole thing was a learning experience.  Somebody changed the audio settings on the camera from auto to manual and I didn’t notice that the setting had been changed.  I didn’t check it and just used the camera.  Grrrrr.  :-(  At any rate, I had to do some extra editing on many of my videos to make them more audible.  This Mongol Rally video - as well as two others that I will be posting soon - turned out well, but it just took some extra time to get them edited.  By the time I was done with the editing, it was CeBIT time and I had tons of videos to shoot, edit and upload there and for a couple of weeks after.  These videos unfortunately got pushed to the back of the line.  I debated whether or not I should still post them but decided even though they aren't that up-to-date anymore, they are still worth a view.  For any of you that love a good travel story or wonder what it would be like to travel from London to Mongolia in a less than perfect car and under adventurous circumstances, check these videos out and consider signing yourself up for Mongol Rally 2008 or 2009!

ReSharper 4.0 Beta ist verfügbar

24.05.2008 13:40:00 | Ozgur Aytekin

JetBrains hat die ReSharper 4.0 Beta Version veröffentlicht und steht für den Download bereit.

ReSharper ist ein Visual Studio Add-In und unterstützt die Entwickler in den Bereichen Code-Analyse, Code-Refactoring, Intellisense und Software-Testing.

In dieser Version unterstüzt ReSharper auch die C# 3.0 Features und LINQ.

Gemäss JetBrains Homepage sind folgende Features in der Version 4.0 Beta vorhanden:

  • Full Support for C# 3.0 and LINQ
    • ReSharper 4 Full Edition and C# Edition provide comprehensive support for C# 3.0, including LINQ, implicitly typed locals and arrays, extension methods, automatic properties, lambda expressions, object & collection initializers, anonymous types, expression trees, and partial methods.
  • Comprehensive Insight into .NET Framework
    • We have analyzed a great share of .NET Framework Class Library, as well as NUnit Framework, and annotated it through external XML files, using a set of custom attributes from the JetBrains.Annotations namespace.
  • Solution-Wide Analysis
    • ReSharper 4.0 provides a full-fledged feature called Solution-Wide Analysis, which looks for erroneous C# code in your whole solution on-the-fly, without compiling it first.
  • Code Cleanup
    • A new, extended reincarnation of what was previously known as Reformat Code. You can now save a myriad of "go-to-next-highlight-then-apply-a-quick-fix" iterations by simply running Code Cleanup!
  • New Refactorings
    • In line with the major message of the current release, all refactorings support C# 3.0. New members of the refactoring family are available, including a pack of C# 3.0-specific refactorings. Plus, we have a surprise for VB.NET aficionados: all refactorings that were previously limited to C# 2.0 are now available for Visual Basic 8.
  • ASP.NET Speedup
    • ReSharper 4.0 significantly speeds up analysis of ASP.NET pages, to enable more web developers benefit from the great toolset that ReSharper provides.

Die URL für den Download: ReSharper 4.0 Beta

Detail Informationen findet ihr unter: What's New in ReSharper 4.0 Beta

Sonntag 2.0, Girl Geek Dinners und TechTalks

23.05.2008 15:43:00 | Lori Grosland

Sonntag 2.0 Am Sonntag den 25. Mai bin ich auf Sonntag 2.0 in München.  Sonntag 2.0 ist unser erstes Mini- Barcamp zum Thema: Web 2.0 und Sicherheits-Aspekte.  Veranstaltungs-Ort ist das NH Hotel München-Dornach (Einsteinring 20, D-85609 Aschheim-Dornach). Mehr Informationen und kostenfreie Anmeldung unter: http://sonntag.mixxt.de/

 

Nächste Woche findet die Webinale in Karlsruhe statt.  Ich bin dabei, um Popfly und Photosynth zu promoten. 

Girl Geek DinnerAm Vorabend von der Webinale (25. Mai) findet ein Girl Geek Dinner statt.  Ein zweites Girl Geek Dinner findet im München am 4. Juni statt.  Ich bin auf beide Veranstaltungen dabei. 

Girl Geek Dinners sind international bereits etabliert, in Deutschland noch neu. Das Konzept basiert auf den London Girl Geek Dinners von Sarah Blow. Ein Girl Geek ist per Definition „eine weibliche Person mit Interesse an Technologie, insbesondere an Computern und Neuen Medien. Allerdings nicht zwangsläufig aus strikt technischer Perspektive, sondern die auch vor allem Technologie als Hilfsmittel sehen und keine Angst davor haben.“  Ein Girl Geek Dinner (GGD) ist ein Event bei dem diese Frauen die Chance haben sich auszutauschen, voneinander zu lernen und Frauen kennen zu lernen, die es in der IT „geschafft“ haben. Girl Geek Dinner sind nicht zwangsläufig „100% Frauen, keine Männer!“-Events, sondern Events an denen Frauen auf Augenhöhe teilnehmen und mindestens 50% der Teilnehmer stellen: Männer sind herzlich eingeladen, aber nur wenn sie von einer Frau mitgebracht werden.  Mehr Info findest Du dazu auf der Webseite: http://girlgeekdinner.de/

 

TECHTALKS

Am Anfang Juni machen mein Kollege Dirk Primbs und ich TechTalks in sechs deutsche Städten zum Thema „Technologieperlen unter der Haube.“  Wir stellen Tools und Technologien wie Deep Zoom, die Live APIs sowie das ein oder andere Research-Projekt vor. Weitere Infos und Anmeldemöglichkeiten gibt es in der Event-Rubrik auf MSDN. Die Teilnahme ist kostenlos. 

Termine und Städte

02.06.2008, Karlsruhe
03.06.2008, Köln
05.06.2008, Berlin
10.06.2008, München
11.06.2008, Hamburg

GirlGeek - Dinner

23.05.2008 12:11:49 | Oliver Scheer

Girl Geek Dinner sind international bereits etabliert, in Deutschland noch neu. Das Konzept basiert auf den London Girl Geek Dinners von Sarah Blow. Ein Girl Geek ist per Definition „eine weibliche Person mit Interesse an Technologie, insbesondere an Computern und Neuen Medien. Allerdings nicht zwangsläufig aus strikt technischer Perspektive, sondern die auch vor allem Technologie als Hilfsmittel sehen und keine Angst davor haben.“  Ein Girl Geek Dinner (GGD) ist ein Event bei dem diese Frauen die Chance haben sich auszutauschen, voneinander zu lernen und Frauen kennen zu lernen, die es in der IT „geschafft“ haben. Girl Geek Dinner sind nicht zwangsläufig „100% Frauen, keine Männer!“-Events, sondern Events an denen Frauen auf Augenhöhe teilnehmen und mindestens 50% der Teilnehmer stellen: Männer sind herzlich eingeladen, aber nur wenn sie von einer Frau mitgebracht werden.  Mehr Info findest Du dazu auf der Webseite: http://girlgeekdinner.de/

Girl Geek Dinner in Karlsruhe am 26.05:

Location - BarRestaurant Coppa Dos

Waldstraße 50

D-76133 Karlsruhe

http://www.coppados.de/

Anmeldung auf der Webseite…

http://girlgeekdinner.de/entry/12/girl_geek_dinner_karlsruhe_260

Girl Geek Dinner in München am 04.06:

Location - Restaurant nam nam

Amalienstraße 25

80333 München

http://www.nam-nam.eu/

Anmeldung auf der Webseite…

http://girlgeekdinner.de/entry/13/girl_geek_dinner_muenchen_0406

HowTo: Einfache Tests - UnitTests (oder keine Angst vor UnitTests…)

22.05.2008 23:33:03 | Robert Mühsig

Einführung

Das Konzept der UnitTests (es gibt noch ein paar weitere Formen) ist bereits seit etlichen Jahren (oder Jahrzehnten?) bekannt. Es gibt viele Testframeworks für fast jede Sprache.
Im Visual Studio 2008 (jedenfalls der Professional/Team System Edition) sind UnitTests sehr einfach zu erstellen - und trotzdem hab ich erst vor kurzem die UnitTests für mich entdeckt. Trotz der Gründe für UnitTests und der Einfachheit kenn ich etliche Projekte, wo diese nicht existieren oder angewendet werden.
Die meisten Entwickler denken, dass UnitTests ziemlich komplex sind und eigentlich unnötig.
Die Gründe der Entwickler sind vielfältig (auch ich hab früher so oder so ähnlich gedacht ;) ) :

  • “Warum nicht einfach ein Konsolenprogramm erstellen oder per Debugger prüfen?”
  • “Ich seh es doch wenn eine bestimmte Komponente nicht funktioniert.”
  • “Für den extra Aufwand hab ich leider keine Zeit.”
  • “UnitTests klingt doch recht kompliziert, da ist mir die Einarbeitungszeit zu hoch.”

Ich bin kein Experte in UnitTests, allerdings haben sie mich bereits nach wenigen Minuten begeistert :)

UnitTests sind sehr schnell gemacht

(Achtung: Diese Aussage nicht auf die Goldwaage legen. Gute und durchdachte UnitTests sind keine leichte Aufgabe - darum gibt es ja z.B. auch eine extra Test Edition von Visual Studio wo sich)
Aber für den Anfang wollen wir die Behauptung mal so stehen lassen - Einfache Tests können sehr schnell durchgeführt werden)

Im Visual Studio 2008 wurde ein extra Template für Tests bereitgestellt:

image

Zudem kann man direkt in einem Projekt per Kontextmenü auf eine Klasse/Methode ein UnitTest erstellen:

image

Aber erst mal zur Grundfrage:

Warum sollte ich Tests machen?

Jeder Entwickler will (hoffentlich) gute und funktionstüchtige Software schreiben, die möglichst fehlerfrei ihren Dienst tut.
In der Zeit wo die Software entwickelt wird, werden sicherlich an vielen Ecken (oder Software-Schichten) Änderungen eingepflegt oder die Applikation muss erweitert werden. Insbesondere in einem Team oder wenn eine größere Umstellung ansteht (Datenbasis wechselt, Logik muss abgeändert werden) wird es kritisch: Laufen alle Komponenten noch wie erhofft?
Je größer die Anwendung, desto größer wird der Aufwand der Betrieben muss, um sicherzustellen, dass alles noch läuft.
Ein Test im UserInterface ist zwar machbar, ist allerdings meist sehr anstrengend und zeit intensiv (sollte natürlich auch gemacht werden).
Es wäre doch viel schöner, wenn die Tests automatisch erfolgen könnten - ohne viel Zeit mit Klicken zu verlieren - auch das die Tests jederzeit ausgeführt werden können wäre doch nett, oder?
Hier kommen die UnitTests: Genau sowas machen UnitTests (und noch mehr ;) ).

Stellen wir uns mal vor…

… dass wir eine nicht ganz triviale Software haben, welche verschiedene Layer (Data/Business etc.) hat. Die Software funktioniert gut - der Kunde ist zufrieden und als Entwickler fühlt man sich wohl.
Wie es meistens ist: Der Kunde möchte eine Änderung. Ein neues Attribut soll hier und da angefügt werden, eine Abfragelogik verändert werden und die Validation der Daten soll anders verlaufen.
Das Problem: Die Änderungen können viele Bereiche betreffen, sodass es leicht passieren kann, dass plötzlich garnichts mehr geht. Aber wo genau hakt es denn? Erstmal überall den Debugger ansetzen und nachverfolgen… hoffentlich übersicht man kein Fehler.
Ergebnis: An dieser Stelle ist es meist für den Entwickler ein etwas mulmiges Gefühl - wird die Software noch genauso funktionieren wie vorher (natürlich mit den Änderungen)?

… nun mal mit Tests vorstellen (ein Gedankenspiel) :

Die verschiedenen Methoden wurden während der Entwicklung der Version 1 bereits mit UnitTests getestet. Daten eintragen, löschen, verändern, laden, validieren, Fehler abfangen usw. - alle Aspekte die wichtig sind, wurden als Test hinterlegt.
Nun kommen die Änderungen: Es werden einige kritische Bereiche verändert, aber nach jeder Veränderung kann man automatisch alle Tests abspielen - schlägt der Test fehl, weiß man, wo Handlungsbedarf besteht. Die eben gemachte Änderung war wohl anscheinend nicht so gut.
Nach einer ganzen Weile: Die Tests werden wieder bestanden - das Herz des Entwicklers schlägt höher. Es können zwar immer noch Fehler auftreten (vielleicht muss ein neuer Test für einen neuen Aspekt noch hinzugefügt werden), aber die Grundzüge der Applikation stimmen noch.

Klingt doch eigentlich gut, aber wie sieht das in der Praxis aus:

Ein sehr (zugegeben) doofes Beispiel:

    public class DataManager
    {
        public bool ConnectToData()
        {
            return true;
        }

        public List<int> GetData()
        {
            return new List<int>() { 1, 2, 3, 4, 5, 6, 7 };
        }
    }

Unser DataManager kann sich zu einer beliebigen Datenquelle verbinden - in unserem Fall sagen wir einfach mal, dass die Verbindung geklappt hat.
Die GetData Methode gibt Daten zurück - in unserem Beispiel ein paar statische Daten.

Da sich die Datenabfrage-Logik ja ändern könnte und da auch die Datenquelle vielleicht sich noch ändert, implementieren wir lieber einen Test dafür:

Create Unit Test…

image 
Methoden auswählen, welche man testen möchte (beide in unserem Fall)…

image 
Name eingeben…

image 

Ein TestProjekt ist entstanden:

image

Generierter Test (dort steht eigentlich bereits das wichtigste drin) :

Visual Studio nutzt MSTest - das Test-Framework von Microsoft. Es ist ähnlich zu nUnit und co.

using DoNot.Fear.UnitTests.Data;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;

namespace DoNot.Fear.UnitTests.Test
{

    /// <summary>
    ///This is a test class for DataManagerTest and is intended
    ///to contain all DataManagerTest Unit Tests
    ///</summary>
    [TestClass()]
    public class DataManagerTest
    {

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        /// <summary>
        ///A test for GetData
        ///</summary>
        [TestMethod()]
        public void GetDataTest()
        {
            DataManager target = new DataManager(); // TODO: Initialize to an appropriate value
            List<int> expected = null; // TODO: Initialize to an appropriate value
            List<int> actual;
            actual = target.GetData();
            Assert.AreEqual(expected, actual);
            Assert.Inconclusive("Verify the correctness of this test method.");
        }

        /// <summary>
        ///A test for ConnectToData
        ///</summary>
        [TestMethod()]
        public void ConnectToDataTest()
        {
            DataManager target = new DataManager(); // TODO: Initialize to an appropriate value
            bool expected = false; // TODO: Initialize to an appropriate value
            bool actual;
            actual = target.ConnectToData();
            Assert.AreEqual(expected, actual);
            Assert.Inconclusive("Verify the correctness of this test method.");
        }
    }
}

Die Kommentare und auch den TestContext kann man löschen - ich hab ihn bisher nicht gebraucht ;)
Achtung: Ich bin kein Experte in den Unit Tests - sondern ist nur eine Art Erfahrungsbericht :)

Machen wir doch erstmal einen einfachen Test ob die Verbindung klappt:

        [TestMethod()]
        public void DataManager_ConnectToData_IsTrue()
        {
            DataManager man = new DataManager();
            Assert.IsTrue(man.ConnectToData());
        }

Sehr schlicht, aber genau das was ich wissen muss. Der Name des Tests sollte ungefähr das beschreiben was er macht - damit man sich später noch zurechtfindet. In diesem Fall prüfe ich einfach, ob die Verbindung zustande kommt.
Die Assert-Klasse hat mehrere Methoden:

image

Jetzt können wir diesen Test durchlaufen und sehen:

image

Jetzt prüfen wir noch die andere Methode:

        [TestMethod()]
        public void DataManager_GetData_IsNotNull()
        {
            DataManager man = new DataManager();
            Assert.IsNotNull(man.GetData());
        }

        [TestMethod()]
        public void DataManager_GetData_CheckForZero()
        {
            DataManager man = new DataManager();
            List<int> result = man.GetData();
            foreach (int number in result)
            {
                Assert.AreNotEqual(0, number);
            }
        }

Die erste Methode prüft, ob überhaupt Werte zurückkommen. Mit dem zweiten Test wollte ich nur mal eine primitive Business-Logik Test machen (”kein Element darf 0 sein”).

Jetzt kann man alle Abspielen:

image

Ergebnis:

image

Schön, oder? :)

Ein Gedankenspiel:

Angenommen in unseren Daten schleicht sich tatsächlich eine 0 ein (Datenabfrage könnte zum Beispiel falsch sein oder es wurden falsche Daten eingetragen), dann schauen wir mal was passiert:

image

Ergebnis:

image

Fail!

image

Idealerweise sollten Tests möglich häufig (sie können sogar automatisch nach jedem Build laufen!) machen - um die Fehlerquelle einzugrenzen.
Angenommen wir haben bei uns einen Fehler in der Abfragelogik oder die Methode (die bei uns nicht existiert, aber existieren könnte) die Daten schreibt, war fehlerhaft oder die Validation fehlgeschlagen ist… (es kann ja viele Quelle geben).

Wir beheben also diesen Fehler (den wir vielleicht sonst nur sehr schlecht gefunden hätten), bis wir wieder das sehen:

image

Resultat beim Entwickler (& beim zufriedenen Kunden) :

image

Der Testcode:

[TestMethod()]
        public void DataManager_ConnectToData_IsTrue()
        {
            DataManager man = new DataManager();
            Assert.IsTrue(man.ConnectToData());
        }

        [TestMethod()]
        public void DataManager_GetData_IsNotNull()
        {
            DataManager man = new DataManager();
            Assert.IsNotNull(man.GetData());
        }

        [TestMethod()]
        public void DataManager_GetData_CheckForZero()
        {
            DataManager man = new DataManager();
            List<int> result = man.GetData();
            foreach (int number in result)
            {
                Assert.AreNotEqual(0, number);
            }
        }


Ergebnis:

Die Vorteile von UnitTests werden sicherlich erst nach und nach bei einem Projekt sichtbar, aber wenn man dies stetig fortführt, reduziert sich die Fehleranfälligkeit erheblich.
Das was ich hier gezeigt habe, ist sicherlich nicht das Ende der Fahnenstange - es gibt neben Unit Tests auch noch andere Tests. Das ist auf der MSDN Testing Seite recht gut beschrieben.

Test Driven Development (TDD) :

TDD beschreibt ein Entwicklungsstil, wo auf Tests besonders viel Wert gelegt wird. Hier werden die Tests immer vor der eigentlichen Implementation geschrieben. Man trifft seine Annahmen und da die Methode (oder die zu testende Komponente) ja noch keine Logik enthält, wird der Test erst fehlschlagen.
Nun geht es darum, den Test erfolgreich zu bestehen. Sobald dies geschafft ist, kann man die Implementation hinterher nochmal überarbeiten. (Refactoring). Nun kann man immer wieder prüfen, ob der Test noch funktioniert oder nicht - wenn er nicht mehr stimmt, dann haben wir wohl was falsch gemacht.
Am Ende haben wir (in der Theorie) jede Methode / Komponente mit Tests ausgestattet.

Unit Tests in ASP.NET MVC, Silverlight & co.:

Eine Klassenbibliothek lässt sich relativ leicht testen. In ASP.NET (WebForms) ist dies allerdings nicht ganz so leicht. In ASP.NET MVC wurde darauf ein besonderer Augenmerk gelegt.
Auch in Silverlight 2 wurde das Thema angegangen.

Weitere Links:

Wer nun etwas neugierig geworden ist, der kann sich auch diese Links anschauen:

Download:

Sample Code

fmx - XNA und Serious Games

22.05.2008 19:16:00 | Lori Grosland

In zahlreichen Sessions auf der fmx erläuterten Microsoft-Sprecher aus Deutschland und den USA wichtige Technologien, wie beispielsweise den Einsatz von XNA Studio zur Spieleentwicklung unter Windows und auf der Xbox.  Vor Ort habe ich mit Dirk Primbs, Microsoft Developer Evangelist, über fmx und XNA gesprochen.  Auch dabei auf dem Microsoft-Stand war Kreativpartner Pixelpark Agentur.  Sie habe ein Showcase zum Thema „Xbox Business Applications“, ein Szenario, bei dem die Xbox-Konsole für Simulationen und E-Learning-Applikationen („Edutainment“) präsentiert.  Ich habe mit Dirk Krause von Pixelpark darüber geredet.

Die Fusion entmystifiziert - Teil 2

22.05.2008 17:55:48 | Klaus Bock

Um die vorhandenen Assemblies im GAC abzufragen gibt es viele Möglichkeiten. Eine, basierend auf dem Abfragen der Registrierung, habe ich in diesem Beitrag auf .NET Snippets.de gefunden. Die mit Sicherheit am häufigsten verwendete Methode dürfte jedoch die Abfrage mit gacutil.exe aus dem SDK sein. Falls jetzt noch die Information benötigt wird, ob ein natives Image einer Assembly vorhanden ist, wird in der Regel der Native Image Compiler ngen.exe verwendet, da gacutil.exe diese Möglichkeit nicht bietet. Unter Verwendung der Fusion-API ist dieses Problem jedoch relativ einfach zu lösen. Hier zum Vergleich die Ausgabe von gacutil.exe und einer Anwendung welche die Fusion-API verwendet. Es wird die Assembly System abgefragt.

gacutil query

Das Tool gacutil.exe gibt richtig die beiden, im GAC installierten, Versionen 2.0.0.0 und 1.0.5000.0 aus. Ob jedoch eines dieser Assemblies als natives Image vorliegt ist so nicht zu erfahren.

 

 

GAC AdminDas Tool GacAdminCmd.exe gibt wie gacutil.exe die beiden Versionen im GAC aus und zusätzlich die gefundene Version 2.0.0.0 aus dem ZAP (Native Images Cache). Die Assembly im ZAP wurde ohne Zuhilfenahme der ngen.exe ermittelt. Um zu erfahren wie, ist eine nähere Betrachtung der statischen Methode CreateAssemblyEnum der Fusion-API notwendig. Der vierte Parameter erwartet ein DWORD, welches ein Flag aus der ASM_CACHE_FLAGS-Enumeration darstellt. Wenn der Wert ASM_CACHE_ZAP, aus der Aufzählung, an den Parameter dwFlags der CreateAssemblyEnum-Methode übergeben wird, sucht die Methode im Native Images Cache nach der Assembly. Wie bereits eingangs erwähnt: relativ einfach.

Die Methode, welche die Assemblies ermittelt und auf den Bildschirm bringt, ist sehr einfach gehalten wie man hier sehen kann.

private static void listAssemblies(string assemblyName, bool listZap)
{
    int i = 0;
    string asm = null;

    Console.WriteLine();

    // Suche nach den Assemblies im GAC
    // wenn assemblyName ein NULL-Verweis ist, werden alle Assemblies
    // im GAC aufgelistet
    AssemblyCacheEnum acEnum = new AssemblyCacheEnum(
									assemblyName,
									AssemblyCacheLocation.Gac);
    
	while ((asm = acEnum.NextAssembly) != null)
    {
        Console.WriteLine("  " + asm);
        i++;
    }
    Console.WriteLine();
    Console.WriteLine(string.Format(
		CultureInfo.CurrentCulture,
        Resources.AsmCountInGacMsg,
		i));

    // Suche nach den Assemblies im ZAP
    if (listZap)
    {
        Console.WriteLine();
        Console.WriteLine();
        i = 0;

        // wenn assemblyName ein NULL-Verweis ist, werden alle Assemblies
        // im ZAP aufgelistet
        acEnum = new AssemblyCacheEnum(
			assemblyName,
			AssemblyCacheLocation.Zap);
        
		while ((asm = acEnum.NextAssembly) != null)
        {
            Console.WriteLine("  " + asm);
            i++;
        }

        Console.WriteLine();
        Console.WriteLine(string.Format(
			CultureInfo.CurrentCulture,
            Resources.AsmCountInZapMsg,
			i));
    }
}

Zunächst wird ein Instanz der AssemblyCacheEnum-Klasse erzeugt und der Name der Assembly sowie der Ort an dem gesucht werden soll im Konstruktor  übergeben. In einer Schleife werden dann die zurückgelieferten Namen auf dem Bildschirm ausgegeben sowie die Anzahl der gefundenen Assemblies mittels der Laufvariablen i ermittelt und ebenfalls ausgegeben.

Da die Implementierung der Fusion-API sehr umfangreich ist, beschränke ich mit hier auf die relevanten Code-Passagen.

Zunächst die bereits erwähnte statische Methode CreateAssemblyEnum

[DllImport("fusion.dll")]
internal static extern int CreateAssemblyEnum(
        out IAssemblyEnum ppEnum,
        IntPtr pUnkReserved,
        IAssemblyName pName,
        AssemblyCacheLocation flags,
        IntPtr pvReserved);

sowie die ebenfalls benötigte Methode CreateAssemblyNameObject. Sie wird benötigt um einen Zeiger auf ein IAssemblyName-Objekt zu erhalten. Hier muss darauf geachtet werden, dass der Parameter szAssemblyName, also der Name der gesuchten Assembly, in eine Unicode-Zeichenfolge gemarshallt wird.

[DllImport("fusion.dll")]
internal static extern int CreateAssemblyNameObject(
        out IAssemblyName ppAssemblyNameObj,
        [MarshalAs(UnmanagedType.LPWStr)]
        string szAssemblyName,
        CreateAssemblyNameObjectFlags flags,
        IntPtr pvReserved);

Zu den Schnittstellen IAssemblyName und IAssemblyEnum ist nicht weiter viel zu sagen. Der Vollständigkeit halber hier die relevanten Passagen.

IAssemblyName:

[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
    Guid("CD193BC0-B4BC-11d2-9833-00C04FC31D2E")]
internal interface IAssemblyName
{
    [PreserveSig()]
    int GetDisplayName(
    StringBuilder pDisplayName,
    ref int pccDisplayName,
    int displayFlags);
}

IAssemblyEnum:

[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
    Guid("21b8916c-f28e-11d2-a473-00c04f8ef448")]
internal interface IAssemblyEnum
{
    [PreserveSig()]
    int GetNextAssembly(
        IntPtr pvReserved,
        out IAssemblyName ppName,
        int dwFlags);
}

Da die aus dem ersten Listing, in der Methode listAssemblies verwendete, Klasse AssemblyCacheEnum sehr umfangreich ist zeige ich hier nur zwei Klassen-Member, den Konstruktor und zwei benötigte private Methode.

public sealed class AssemblyCacheEnum : IDisposable
{
    #region Class Members

    private IAssemblyEnum assemblyEnum = null;

    private IAssemblyName fusionName = null;

    #endregion

    public AssemblyCacheEnum(
			string assemblyName,
			AssemblyCacheLocation location)
    {
        // HRESULT erzeugen
        int hr = 0;

        if (assemblyName != null)
        {
            hr = NativeMethods.CreateAssemblyNameObject(
                out fusionName,
                assemblyName,
                CreateAssemblyNameObjectFlags.ParseDisplayName,
                IntPtr.Zero);
        }

        if (hr >= 0)
        {
            hr = NativeMethods.CreateAssemblyEnum(
                out assemblyEnum,
                IntPtr.Zero,
                fusionName,
                location,
                IntPtr.Zero);
        }

        if (hr < 0)
        {
            Marshal.ThrowExceptionForHR(hr);
        }
    }

    [SecurityPermission(
	 SecurityAction.LinkDemand,
	 UnmanagedCode = true)]
    private string getNextAssembly()
    {
        int hr = 0;

        // eine Instanz der IAssemblyName-Schnittstelle erzeugen.
        fusionName = null;

        // prüfen ob das Ende der Aufzählung bereits erreicht wurde
        if (done)
        {
            return null;
        }

        // jetzt das nächste IAssemblyName-Objekt
		// von assemblyEnum holen
        hr = assemblyEnum.GetNextAssembly(
							(IntPtr)0,
							out fusionName,
							0);

        if (hr < 0)
        {
            Marshal.ThrowExceptionForHR(hr);
        }

        // prüfen ob fusionName einen Wert hält
        if (fusionName != null)
        {
            // TODO: Fehlerbehandlung einbauen
            return getFullName(fusionName);
        }
        else
        {
            // keine Assembly mehr gefunden.
            done = true;
            return null;
        }
    }

    [SecurityPermission(
	 SecurityAction.LinkDemand,
	 UnmanagedCode = true)]
    private static string getFullName(IAssemblyName fusionAsmName)
    {
        int iLen = 1024;
        StringBuilder sDisplayName = new StringBuilder(iLen);

        int hr = fusionAsmName.GetDisplayName(
								sDisplayName,
								ref iLen,
								(int)AssemblyNameDisplayFlags.All);

        if (hr < 0)
        {
            Marshal.ThrowExceptionForHR(hr);
        }

        return sDisplayName.ToString();
    }
}

Manch einem mag die Implementierung der Fusion-API sehr aufwendig erscheinen. Wenn sie für nur eine Anwendung gesehen wird, gebe ich ihm recht. Doch einmal als Bibliothek erstellt, ist sie für jedes zukünftige Projekt verfügbar oder kann auch weiter gegeben werden. Unter diesem Aspekt halte ich den Aufwand für gerechtfertigt.

Technorati-Tags: | | |

Reflector Version 5.1.2.0 verfügbar

22.05.2008 13:21:00 | Klaus Bock

Seit Anfang Mai ist die aktualisierte Version 5.1.2.0 des .NET Reflector von Lutz Roeder verfügbar. Die Reflector Add-Ins, auf CodePlex gehostet, haben auch einige Neuerungen erfahren.

Wer öfter mal Com-Bibliotheken verwendet, sollte sich unbedingt das ComLoader Add-In genauer ansehen. Damit ist es möglich eine Com-Bibliothek auszuwählen und aus dieser eine verwaltete Com-Interop Assembly erstellen zu lassen. Bei der Auswahl der Com-Bibliothek können gleich verschiedene Optionen, wie etwa der zu verwendende Namensraum, eine SNK-Datei für den Public Key oder die Assembly Version, mit gegeben werden. Wie mit den importierten Schnittstellen umgegangen werden soll kann hier ebenso eingestellt werden, wie der Umgang mit Array's.

 

Technorati-Tags: | |

Online Vortrag am 27. Mai 2008 zum Thema ReSharper

21.05.2008 13:05:19 | Albert Weinert

Ich werde am Dienstag den 27. Mai 2008 einen Online Vortrag zum Thema ReSharper 4.0 machen. Dies geschieht im Rahmen der .net user group Köln Online Usertreffen. Es wird also das erste reine Online "treffen". Mal schauen was dabei rumkommt.

Der Vortrag wird über Office Live Meeting 2007 gehalten. Den kostenlosen Client kann man herunterladen. Eine Test nach der Installation ist unter folgender Seite möglich. http://esd.placeware.com/lm2007test/

ReSharper 4.0

Geplant sind folgende Themenbereiche die ReSharper beherrscht.

  • Quelltext Navigation
  • Refactoring
  • Quelltext Erzeugung
  • Quelltext Analyse
  • Unit Testing
  • LIve Templates

ReSharper ist ein sehr mächtiges Tool, welches jedoch Erklärung bedarf um den Einstieg zu erleichtern. Dies versuche ich mit dem Vortrag zu erreichen. Sicherlich wird auch der eine oder anderen ReSharper Anwender auch noch was neues Kennenlernen, wie ich auch ständig auf's neue Überrascht bin was ReSharper noch kann.

Ab 18:30 Uhr könnt Ihr euch hier anmelden. Es besteht die Möglichkeit des Sprachchats.

Eingeladen sind natürlich alle interessierte, nicht nur Mitglieder der .net user group Köln.

Ausgabe eines GridViews verändern - DataBound und RowDataBound Events

19.05.2008 23:05:00 | Peter Bucher

Vielfach kam in den Communities die Frage auf, wie es sich denn die Anzeige des GridViews verändern lässt.
Als Antwort kommt "RowDataBound Event".

Genau auf diesen Event will ich hier eingehen und anhand eines Beispiels zeigen, wie dieser Event benutzt werden kann.

Zitat aus "Hinweise":

Bevor das GridView-Steuerelement gerendert werden kann, muss jede Zeile im Steuerelement an einen Datensatz in der Datenquelle gebunden werden. Das RowDataBound-Ereignis wird ausgelöst, wenn eine Datenzeile (dargestellt durch ein GridViewRow-Objekt) an Daten im GridView-Steuerelement gebunden wird. Dadurch können Sie eine Ereignisbehandlungsmethode bereitstellen, die bei jedem Auftreten dieses Ereignisses eine benutzerdefinierte Routine ausführt, beispielsweise das Ändern der Werte der an die Zeilen gebundenen Daten.

 

und es steht weiter...

Ein GridViewRowEventArgs-Objekt wird an die Ereignisbehandlungsmethode übergeben, wodurch Sie auf die Eigenschaften der gebundenen Zeile zugreifen können. Wenn Sie auf eine bestimmte Zelle in der Zeile zugreifen möchten, verwenden Sie die Cells-Eigenschaft des GridViewRow-Objekts, das in der Row-Eigenschaft des GridViewRowEventArgs-Steuerelements enthalten ist. Sie können außerdem bestimmen, welcher Zeilentyp (Headerzeile, Datenzeile usw.) gebunden wird, indem Sie die RowType-Eigenschaft verwenden.

Das heisst, mit dem Event "RowDataBound" der GridView Klasse, ist es möglich, jede Zeile direkt nach der Datenbindung zu modifizieren.

Methoden die das Ereignis abonnieren, müssen einer festgelegten Signatur entsprechen.
Visual Studio macht das im Normalfall selber per Tastenkombination für uns.

 

Folgende, die benötigte Signatur:

void grdTest_RowDataBound(object sender, GridViewRowEventArgs e)

 

Eine Methode kann bspw. so aussehen:



/// <summary>
/// Formatiert die Tabelle ansehlich
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void grdTest_RowDataBoundAllgemein(object sender, GridViewRowEventArgs e) {
    if (e.Row.RowType == DataControlRowType.DataRow) {
        string text = e.Row.Cells[2].Text;
        e.Row.Cells[2].Text = Tools.WordWrap(text, 25) + "...";
        e.Row.Cells[2].CssClass = "fixedWidth";
    }
}

GridViewDataBoundEvents

Diese macht nichts weiter, als für alle Zeilen die dem DataControlRowType.DataRow entsprechen, denn Text zu kürzen und der dritten Zelle von Links eine CSS Klasse hinzuzufügen, damit sie eine fixe Breite einnimmt.

 

Zum Download findet ihr eine Beispielanwendung, diese enthält ein GridView das mit Zufallsdaten gefüllt wird.
Mit vier Behandlungsmethoden für DataBound und RowDataBound enthält und die Tabelle in der Ausgabe modifiziert.
Mithilfe des Suchfilters können Textdaten aus dem Feld "Text" hervorgehoben werden, die dem Suchwort entsprechen.

Mit dem Priority-Farbe Link können die Farben für die Priority Spalte hervorgehoben werden
Mithilfe des Priority-Summe Links wird in der FooterRow (Fuss-Zeile) jeweils eine Summe aller Priorities dargestellt.
Im nächsten Abschnitt findet ihr den benötigten ASPX Code, den ich der Übersichtshalber ein bisschen beschnitten habe:

 

 

 



<form id="aspnetform" defaultbutton="btnSubmit" runat="server">
    <h1>GridViewDataBoundEvents</h1>
    <asp:Label ID="lblSearch" AssociatedControlID="txtSearch" Text="Suche in Text" runat="server" />
    <asp:TextBox ID="txtSearch" runat="server" />
    <asp:Button ID="btnSubmit" Text="Finden" runat="server" />
    <br />
    <br />
    <a id="search" href="?mode=search" runat="server">Suchfilter</a>
    <a id="color" href="?mode=color" runat="server">Priority-Farbe</a>
    <a id="sum" href="?mode=sum" runat="server">Priority-Summe</a>
    <br />
    <br />
    <asp:GridView ID="grdTest" GridLines="None" runat="server" />
</form>

Es steht ein Suchformular zur Verfügung, das aktiv wird, wenn der Suchfilter aktiviert wird.
Die kleine Navigation mit den normalen Links soll euch zeigen, wie verschiedene RowDataBound Ereignishandler je nach Auswahl abonniert werden können.

Im Page_Load der Beispielseite werden die Daten aus einer Zufallsquelle geladen, die Filter je nach Auswahl zugewiesen und dem aktiven Link eine CSS Klasse hinzugefügt.
Zudem werden die Daten beim ersten Laden der Seite gebunden und ein Klick Event des Suchen Buttons registriert.



protected void Page_Load(object sender, EventArgs e) {
    // Daten besorgen
    List<Task> data                  = new RandomData(10).RandomList;
    this.grdTest.DataSource      = data;

    // Filter Mode auswählen
    string mode = this.Request.QueryString["mode"];
    if (string.IsNullOrEmpty(mode)) {
        mode = String.Empty;
    }

    // Allgemeine Formatierungen anwenden
    this.grdTest.RowDataBound += this.grdTest_RowDataBoundAllgemein;

    switch (mode) {
        case "sum":
            // Summe anzeigen
            this.grdTest.DataBound += grdTest_DataBound;
            this.sum.Attributes.Add("class", "active");
            break;
        case"color":
            // Farben zu den Priority Zahlen anzeigen
            this.grdTest.RowDataBound += this.grdTest_RowDataBoundPriorityBackColor;
            this.color.Attributes.Add("class", "active");
            break;
        case "search":
            // Suchwörter bzw. dessen Zeilen hervorheben
            this.grdTest.RowDataBound += this.grdTest_RowDataBoundTextSearch;
            this.search.Attributes.Add("class", "active");
            break;
        default:
            break;
    }

    // Button.Click Eventhandler anmelden
    this.btnSubmit.Click += this.btnSubmit_Click;

    // Daten beim ersten Seitenaufruf binden
    if (!this.IsPostBack) {
        this.grdTest.DataBind();
    }
}

 

Diese Routine hebt Texte hervor, die ein Treffer in der Suche haben



/// <summary>
/// Erhellt die Zeilen, bei denen ein der gesuchte Begriff von "txtSearch" vorkommt
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void grdTest_RowDataBoundTextSearch(object sender, GridViewRowEventArgs e) {
    if (e.Row.RowType == DataControlRowType.DataRow) {
        string text = e.Row.Cells[2].Text;
        if ((!string.IsNullOrEmpty(this.txtSearch.Text))
            && text.IndexOf(this.txtSearch.Text) > -1) {
            e.Row.Cells[2].ForeColor = Color.Red;
        }
    }
}

 

Diese Methode vergibt Farben, je nach dem was für Werte das Feld "Priority" enthält.
Hier wird direkt über die DataBinder.Eval() Methode gearbeitet. Das ist genauer als über die jeweilige Zelle zu gehen.

Denn die Zelle, bzw. dessen Index kann sich ändern, ein Feldname nicht so häufig.



/// <summary>
/// Vergibt je nach Zahlenwertung eine Hintergrundfarbe für die aktuelle Zelle
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void grdTest_RowDataBoundPriorityBackColor(object sender, GridViewRowEventArgs e) {
    if (e.Row.RowType == DataControlRowType.DataRow) {
        TableCell priortyCell = e.Row.Cells[3];

        switch(int.Parse(DataBinder.Eval(e.Row.DataItem, "Priority").ToString())) {
            case 0:
            case 1:
            case 2:
                priortyCell.BackColor = Color.Gray;
                break;
            case 3:
            case 4:
            case 5:
                priortyCell.BackColor = Color.Orange;
                break;
            case 6:
            case 7:
            case 8:
                priortyCell.BackColor = Color.OrangeRed;
                break;
            case 9:
            case 10:
                priortyCell.BackColor = Color.Red;
                break;
            default:
                break;
        }
    }
}

 

Und was passiert jetzt, wenn ich TemplateFields habe?

Wenn die Vorgaben nicht passend sind, ist ein TemplateField Mittel zum Zweck und dazu noch ein gutes!
In einem ItemTemplate eines TemplateFields können beliebige Controls platziert werden, bspw.:

Folgend der Code, des zweiten GridViews:



<asp:GridView ID="grdTest2" AutoGenerateColumns="false" GridLines="None" runat="server">
    <Columns>
        <asp:BoundField HeaderText="Id" DataField="Id" />
        <asp:BoundField HeaderText="Title" DataField="Title" />
        <asp:TemplateField HeaderText="Text">
            <ItemTemplate>
                <asp:Literal ID="litCountWords" runat="server" />
                Wörter und <asp:Literal ID="litCountWordsDisplayed" runat="server" />
                 werden angezeigt.
                 <asp:Panel ID="container" runat="server" style="border: 1px solid gray; padding: 4px; margin: 4px;">
                    <asp:Literal ID="litText" runat="server" />
                 </asp:Panel>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

Hierbei werden ein paar Controls platziert und eine eindeutige ID vergeben.
Da diese Templates MultipleTemplateInstances sind, werden die IDs automatisch einzigartig gehalten.
Nachteil dabei ist, das nur noch der indirekte Zugriff per <Control>.FindControl() möglich ist. Bei SingleInstence Templates ist der Zugriff direkt über die ID möglich.

Siehe: http://www.nikhilk.net/SingleInstanceTemplates.aspx

Durch eine relativ einfach Manipulation kann der Inhalt bereitgestellt werden:



/// <summary>
/// Wertet den Inhalt aus
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void grdTest2_RowDataBound(object sender, GridViewRowEventArgs e) {
    if (e.Row.RowType == DataControlRowType.DataRow) {
        e.Row.Cells[2].CssClass = "fixedWidth";

        Literal countWords = e.Row.FindControl("litCountWords") as Literal;
        Literal countWordsDisplayed = e.Row.FindControl("litCountWordsDisplayed") as Literal;

        Literal text = e.Row.FindControl("litText") as Literal;

        string content = DataBinder.Eval(e.Row.DataItem, "Text").ToString();
        text.Text = Tools.WordWrap(content, 25) + "...";

        countWords.Text = content.Split(' ').Length.ToString();
        countWordsDisplayed.Text = text.Text.Split(' ').Length.ToString();
    }
}

Die Beispielanwendung könnt ihr hier Downloaden:

Referenzen:

Wöchentliche Rundablage: Silverlight 2, ASP.NET MVC, C# 3.0, .NET 3.5 SP1…

19.05.2008 21:41:12 | Robert Mühsig

Silverlight 2:

ASP.NET MVC / ASP.NET:

Development:

.NET 3.5 SP1 / .NET / C# / Visual Studio:

Javascript:

Jobs, Jobs, Jobs!

19.05.2008 11:10:53 | Oliver Guhr

mitarbiter werben

Das Unternehmen für das Robert und ich arbeiten, die T-Systems Multimedia Solutions GmbH sucht zur Zeit 200 Mitarbeiter Deutschland weit. Um die offenen Stellen zu besetzen wurde allen Mitarbeitern bis zu 1000€ pro geworbenen Mitarbeiter geboten.
Wir Teilen uns die Kohle mit dir! Schicke dazu nach erfolgreicher Bewerbung eine Mail an Robert oder mich. Weitere Informationen zur Bewerbung findest du hier.

Offene Stellen im Bereich IT

Offene Stellen im Bereich Non-IT

T-Systems Multimedia Solutions - A Great Place To Work!

MVC Storefront - Real World Application Building Excercise: ASP.NET MVC, TDD & more

18.05.2008 22:22:21 | Robert Mühsig

Schonmal etwas von Test-Driven-Developement gehört oder ASP.NET MVC?

Rob Conery (Entwickler von SubSonic und nun bei ASP.NET Team beschäftigt) versucht sich nun genau an diesen Dingen und dokumentiert dies - mittlerweile sind so bereits 10 Teile zusammengekommen:

Ich finde diese Videos sehr interessant gemacht - vor allem sieht man, warum welche Architekturentscheidung so oder so getroffen wurde - Rob erklärt ziemlich präzise jeden einzelnen Schritt und alles im TDD Umfeld.

Ich empfehle auch die Kommentare zu lesen, da dort bereits einige Architekturentscheidungen durch diskutiert wurden. Diese Diskussionen sind doch sehr lehrreich - insgesamt finde ich die momentane Architektur, welche Rob gewählt hat, sehr interessant.

Das Ganze gibts auch auf Codeplex zum Download.

Buchempfehlung: The Pragmatic Programmer

18.05.2008 21:00:56 | Robert Mühsig

Bücher sind für viele Programmierer ein Graus - sie veralten zu schnell und die beschriebenen Techniken sind schnell abgelöst.
Es gibt allerdings auch Bücher, die selbst nach Jahren noch einiges Wissen weitergeben. Eines davon ist das Buch “The Pragmatic Programmer“.

In dem Buch werden viele praktische Tipps weitergegeben - vieles ist bestimmt schon irgendwie bekannt (z.B. das eine “lose Kopplung” zwischen irgendwelchen Systemteilen günstig ist oder das eine Source Control unbedingt eingesetzt werden sollte), aber trotzdem gibt es sehr coole Aha-Effekte.
Manche Sachen treffen jetzt auch nicht unbedingt auf mich zu bzw. werde ich mich damit erst mal nicht beschäftigen, aber als prinzipielle Gedanke ist es gut. Vor allem Anfänger sollten dieses Buch mal durchlesen :)

Amazon.de Widgets

Software-Tipp: Microsoft WorldWide Telescope (für Hobby Astronomen)

18.05.2008 20:14:56 | Robert Mühsig

Microsoft Research hat eine nette Spielerei freigegeben: WorldWide Telescope. Es ist “ähnlich” wie Google Earth - nur das man hier durch das Weltall sich navigieren kann. Erst war ich erstmal leicht gelangweilt, aber wenn man sich näher die tollen Bilder anschaut, dann kann man eine ganze Weile hin und her zommen.
Hier ein paar Screenshots:

image 
(das Interface)

image

image

Mit einer dicken Internetleitung sieht es natürlich besser aus ;)

ADO.NET Entity Data Model und EntityDataSource in Visual Studio 2008

18.05.2008 19:23:00 | Ozgur Aytekin

In diesem Beitrag möchte ich mit einer Step-by-Step Anleitung euch zeigen, wie wir einfach und schnell eine einfache ASP.NET Web Application-Anwendung erstellen mit der wir die Daten in einer Datenbanktabelle anzeigen und bearbeiten können.

Dabei werde ich mit Visual Studio 2008 Service Pack 1 Beta veröffentliche ADO.NET Entity Model und EntityDataSource Komponente (Component) als Datenbank-Schnittstelle verwenden.

Schritt 1: Ein neues ASP.NET Web Application Projekt erstellen

Visual Studio 2008 starten und Menü Eintrag File - New Project auswählen.

Anschließend Visual C# - ASP.NET Web Application Template auswählen und EntityDataSourceSample0002 als Projektname definieren.

Step001 - Add New Project - ASP.NET Web Application

Schritt 2: Als nächstes Erstellen wir eine ADO.NET Entity Data Model-Klasse

Mit Hilfe des Project - Add Component Menü Eintrag den Auswahl-Dialog für Projekt-Elemente starten.

Im Dialog ADO.NET Entity Data Model-Element auswählen und AdventureWorks.edmx als Name definieren.

Step002 - Add New Item - ADO.NET Entity Data Model

Schritt 2a: Entity Data Model Wizard-Dialog

Im Wizard "Generate from database"-Element auswählen.

Step002a - Entity Data Model Wizard - Generate from database

Schritt 2b: Datenbank-Verbindung (Database connection)

In diesem Dialog definieren wir die Datenbank-Verbindung (Database connection). Zusätzlich wird auch der Name des Web.Config-Eintrages für die ConnectionString definiert.

In dem folgenden Beispiel wird ein SQL Server 2008 mit der AdventureWorks-Datenbank verwendet und der Eintrag im Web.Config-File heißt AdventureWorksEntitites.

Step002b - Choose Your Data Connection

Schritt 2c: Datenbank-Objekt (Database object) auswählen

Erst hier definieren wir, welche Datenbank-Tabelle(n) (Database table(s)) für unser Model relevant sind.

In dem folgenden Beispiel wird nur die CountryRegion-Tabelle ausgewählt. Zusätzlich wird der Name für den Model Namespace definiert. Im Beispiel wird AdventureWorksModel als Namespace verwendet.

Step002c - Choose Your Database Objects

Als Resultat erhalten wird unser AdventureWorks-Model mit der CountryRegion-Entity Klasse (Entity Class)

Step002d - AdventureWorksModel - CountryRegion Entity

Schritt 3: EntityDataSource-Komponente (Component)

In diesem Schritt werden wir die EntityDataSource-Komponente in unsere Seite einbinden und Konfigurieren.

Wir wechseln in das Design-Modus des Default.aspx-Elements. Einfach Solution Explorer auswählen und auf das Default.aspx-Element doppelklicken.

Im Toolbox unter dem Abschnitt Data sehen wir unseren EntityDataSource-Komponente (Component).

Step003 - EntityDataSource

Mit Drag & Drop die EntityDataSource-Komponente (Component) auf das Default.aspx-Element ziehen und los lassen.

Schritt 3a: EntityDataSource - DataSource-Eigenschaft konfigurieren (Configure Data Source)

Als nächstes werden wir die DataSource-Eigenschaft der EntityDataSource-Komponente konfigurieren. Für die Konfiguration kann der Eintrag Configure Data Source (wie im untenstehenden Bild ersichtlich) ausgewählt werden.

Step003a - EntityDataSource - Configure Data Source

Schritt 3b: ObjectContext-Konfigurieren (Configure ObjectContext)

Die ConnectionString und DefaultContainerName Informationen werden im folgenden Dialog definiert.

"Die Beta 1 des Visual Studio 2008 Service Packs hat leider einen Fehler (Bug). Ich werde euch zeigen, wie man diesen Fehler umgehen kann."

Namen Connection markieren und den Eintrag AdventureWorksEntities auswählen.

Step003b - EntityDataSource - ConnectionString

Wenn wir versuchen, den DefaultContainerName-Eigenschaft zu definieren, dann erhalten wir folgenden Fehlermeldung (Fehler (Bug) in Visual Studio 2008 ServicePack 1 Beta): The Entity Data Model metadata specified in the connection string could not be loaded due the following error(s): Unable to load specified metadata resource.

Step003c - EntityDataSource - Error - DefaultContainerName

Schritt 3c: Fehler (Bug) Korrektur

Die Fehlermeldung mit OK bestätigen und den Wizard mit Cancel abbrechen.

In der Web.Config-Datei wurde im Abschnitt ConnectionString ein falscher Eintrag verursacht diesen Fehler:

Step003ca - EntityDataSource - Error - DefaultContainerName - Correction

Die "*" müssen mit dem Projektnamen (Project name) bzw. Assemlby-Namen (Assembly name) ersetzt werden.

Step003cb - EntityDataSource - Error - DefaultContainerName - Correction

Die Datei speichern und neu KOMPILIEREN (Build).

Anschließend nochmals zurück auf das Design-Modus der Default.aspx-Seite wechseln und den EntityDataSource-Element konfigurieren (siehe Schritt 3a).

Schritt 3d: DefaultContainerName auswählen

Als DefaultContainerName den Eintrag AdventureWorksEntites auswählen.

Step003d - EntityDataSource - DefaultContainerName

Schritt 3e: Daten-Selektion konfigurieren (Configure Data Selection)

In diesem Schritt definieren wir, welche Funktionalitäten für unsere CountryRegion-Klasse zur Verfügung stellen soll.

Gemäß folgende Bild die Einstellungen vornehmen und den Dialog mit Finish abschließen.

Step003e - EntityDataSource - Configure Data Selection

Schritt 4: GridView-Element für die Datenanzeige und Bearbeitung

Für die Anzeige und Bearbeitung der Daten benötigen wir ein GridView-Element. Einfach ein neues GridView-Element mit Drag & Drop auf die Default.aspx-Seite ziehen.

Step004 - DataGridView

Schritt 4a: GridView DataSource-Eigenschaft (Property)

Als nächstes konfigurieren wir die Data Source-Eigenschaft (Property) des GridView-Controls. Als Data Source den EntityDataSource1-Eintrag auswählen.

Step004a - DataGridView - Choose Data Source

Unser GridView-Control wie folgt aus:

Bitte hier auch die Optionen Enable Paging, Enable Sorting, Enable Editing, Enable Deleting und Enable Selection auch ankreuzen.

Step004b - DataGridView - GridView Tasks

Jetzt können wir unser Beispiel-Projekt mit F5 starten.

Wenn bei euch auch die "Debugging Not Enabled"-Meldung erscheint, einfach mit OK weitermachen.

Step005 - Run - Modify the Web.config file to enable debugging

Nach eine "einbißchen lange" Wartezeit sehen wir in unserem Browser (in meinem Beispiel Internet Explorer) die Default.aspx-Seite mit GridView und die CountryRegion-Daten.

Step006 - Default.aspx in Internet Explorer

Das Beispielprojekt findet ihr unter: EntityDataSourceSample0002

Viel Spaß beim ausprobieren.

Für Feedbacks über die Kommentar-Funktionalität wäre ich dankbar, ob das Beispiel-Projekt bei euch auch funktioniert hat.

Sonntag 2.0

18.05.2008 17:13:39 | Oliver Scheer

Sonntag 2.0 – ein Mini-Barcamp zum Thema: Web 2.0 und Sicherheits-Aspekte

Schon mal auf einem Barcamp gewesen? Am Sonntag den 25.05.2008  findet unser erstes Mini- Barcamp in München statt zum Thema: Web 2.0 und Sicherheits-Aspekte.  Mehr Informationen und kostenfreie Anmeldung unter: http://sonntag.mixxt.de/

2842_gra_logo_sonntag20

XTOPIA 2008 kommt ...

18.05.2008 17:06:46 | Oliver Scheer

Am 17. und 18.11. findet die XTOPIA zum zweiten Mal statt.

Wieder in Berlin, dieses Mal jedoch im Berliner ICC. Am 16. November findet zusätzlich noch eine Pre-Conference statt. Die Microsoft Web-Konferenz für Web- und UI-Entwickler, IT-Entscheider und Designer geht damit ins zweite Jahr... wir freuen uns auf Sie! Bleiben Sie auf dem Laufenden über den RSS-Feed auf www.xtopia.de. In Kürze finden Sie dort ausführlichere Informationen und natürlich auch die Möglichkeit zur Registrierung.

Mehr Infos gibt es unter www.xtopia.de

Die Fusion entmystifiziert - Teil 1

18.05.2008 16:05:36 | Klaus Bock

Wir alle benutzen sie mehr oder weniger oft, doch kaum einer nimmt Notiz von ihr; die Fusion-API. Egal ob mit gacutil.exe eine Assembly dem GAC hinzugefügt wird oder ein MSI-Paket eine Assembly im GAC installiert, es ist immer die Fusion-API die das erledigt. Selbst der Assembly Cache Viewer des Explorer, die shfusion.dll, verwendet die Fusion-API.

Ich stand immer wieder vor dem Problem verschiedene Assemblies im GAC zu installieren auf Maschinen auf denen kein .NET SDK installiert ist, also auch keine gacutil.exe. Der Assembly Cache Viewer ist zu umständlich da, soweit ich es weiß, er nicht gescriptet werden kann. Jedesmal ein Setup-Projekt erstellen; das kann es doch nicht sein! Also begann ich eine kleine Konsolenanwendung um mir die Aufgabe ein wenig zu erleichtern. Dachte ich!

Mir fiel sehr schnell eine Eigenart der CLR auf: wenn eine Assembly geladen wurde um mittels Reflection die Attribute der Assembly auszulesen, kann diese Assembly weder verschoben noch gelöscht werden. Nach einigen weniger Erfolgreichen Recherchen, stieß ich auf den Sample Managed GAC API Wrappers Artikel von Junfeng Zhang. Nachdem ich den Ansatz gefunden hatte, sah ich mir die Fusion (Referenz zur nicht verwalteten API) einmal genauer an. Heureka! Das ist es.

Als Basis für meinen GacWrapper habe ich den oben erwähnten Artikel von Junfeng Zhang verwendet. Doch mein erstes Ziel, das Auslesen der Assembly-Attribute unter Angabe des Dateinamens, war mit dieser Beispiel-Implementierung nicht zu lösen. Mit der Methode GetAttribute der Schnittstelle IReferenceIdentity könnte dieses Problem jedoch gelöst werden. Die Methode gibt in der Original-Implementierung ein HRESULT zurück und liefert den benötigten Wert mittels eines out-Parameter. Da out-Parameter vermieden werden sollten, habe ich die Methode so geändert, dass der Wert direkt als string zurückgegeben wird. Hier die Schnittstelle im Code:

Jetzt wird noch eine Methode benötigt die der Schnittstelle mitteilt, welche Assembly behandelt werden soll. Die Fusion-API bietet hier die statische Methode GetAssemblyIdentityFromFile an, welche als Rückgabewert einen Zeiger auf ein IUnknown-Objekt liefert. Da die Implementierung der IReferenceIdentity als ComInterfaceTyp InterfaceIsUnKnown verfügbar ist, sollten hier keine Probleme auftauchen. Die statische Methode erwartet den Pfad zur Assembly und die Guid der verwendeten Schnittstelle. Da ich, wenn möglich, Zeiger im verwalteten Code vermeide habe ich die Implementierung der statischen Methode so geändert, dass ein Object zurückgegeben wird. Das Rückgabe-Objekt kann dann in ein Objekt vom Typ IReferenceIdentity geparst werden. Natürlich muss hier das zurückgegebene Objekt in den Typ IUnknown gemarshallt werden. Auch muss unbedingt beachtet werden, dass im DllImport-Attribute der Zeichensatz Unicode beim marshalling verwendet wird. Die Umsetzung in Code sollte dann etwa so aussehen:

Soweit zur Implementierung des nicht verwalteten Codes. Als nächstes habe ich eine Klasse gebildet in der auf die Assembly-Attribute lesend zugegriffen werden kann. Da die Möglichkeit zur Iteration durch die Attribute gegeben werden soll, verwende ich ein StringDictionary um die ermittelten Attribute in einer Klasse vor zuhalten. Hier ein Auszug daraus:

Bis jetzt ist die Möglichkeit geschaffen die Attribute einer Assembly, nur anhand des Dateinamens, auszulesen. Die Assembly wurde dabei nicht von der CLR geladen, kann also verschoben, gelöscht oder wie auch immer gehandhabt werden.

Die Fusion-API bietet deutlich mehr als diese eine Möglichkeit. Ich werde nach und nach, auch soweit ich Zeit dazu finde, diese Serie erweitern.

Technorati-Tags: | |

Visual Studio 2008 Service Pack 1 Beta Installation - Fatal error during installation

18.05.2008 15:53:00 | Ozgur Aytekin

Die Installation von Visual Studio 2008 Service Pack 1 Beta hat bei mir immer wieder fehlgeschlagen.

Jedes Mal wurde die Installation des Service Pack 1 Beta mit der Fehlermeldung "Fatal error during installation" abgebrochen.

Visual_Studio_2008_Service_Pack_1_SP1_Beta_Fatal_Error_During_Installation

Unter folgenden Forum Eintrag bei forums.microsoft.com konnte ich die Hilfe finden.

Fatal Error during Installation of Visual Studio 2008 service pack 1 beta

Nach der Installation der Full-Installer des .NET Framework 3.5 Service Pack 1 Beta konnte ich den Service Pack 1 Beta für Visual Studio 2008 erfolgreich installieren.

Die URL für die Full-Installer des .NET Framework 3.5 Service Pack 1 Beta: Microsoft .NET Framework 3.5 Service pack 1 Beta (Full-Installer)

Performance Tipp: Eine DB Connection global für einen Page Request definieren.

16.05.2008 23:31:00 | Jürgen Gutsch

Im Moment arbeite ich gerade an einer kleinen Communitiy Anwendung (ja klein, muss ja nicht immer groß sein) die standardmäßig eine Access Datenbank nutzt. Datenbankzugriffe sehen im Moment so aus, dass ich für jede Abfrage eine neue Datenbankverbindung öffne und anschließend wieder schließe. Eigentlich eine normale Prozedur:

using (OleDbConnection conn = new OleDbConnection(this.ConnectionString))
{
  string cmdText = "DELETE FROM [emails] WHERE [mailid]=?";
  using (OleDbCommand cmd = new OleDbCommand(cmdText, conn))
  {
    cmd.Parameters.Add("mailid", OleDbType.Guid).Value = ID;
    cmd.ExecuteNonQuery();
  }
}

Und ausreichend für einen einzelnen Zugriff. Meine Anwendung macht aber pro Page Request mindestens fünf Zugriffe; im Schnitt sind es sogar mehr.

In einem Thread auf MyCSharp, in dem es um zu schließende Connections beim Verlassen einer Website ging, wurde ich von Peter auf eine Diskussion auf Google Groups aufmerksam gemacht, in der es darum ging Datenbankverbindungen global zur Verfügung zu stellen. Stefan stellte dabei einen interessanter Ansatz vor:

Er definierte eine Klasse, die für das Öffnen und Schließen der Datenbankverbindung zuständig ist und die offne Verbindung hält. Diese Klasse wird in der Global.asax bei Application_BeginRequest instanziert, die Connection wird geöffnet und anschließend wird das erzeugte Objekt im aktuellen HttpContext gespeichert. Bei Application_EndRequest wird das Objekt aus dem HttpContext ausgelesen und die Verbindung geschlossen. Im Prinzip eine einfache und geniale Lösung. Die Connection kann jetzt überall in der Anwendung aus dem HttpContext geholt und genutzt werden.

Da ich wie erwähnt nach Optimierungsmöglichkeiten suchte, lag es nahe Stefans Vorschlag auszuprobieren, zumal mir langsam die Ideen für weitere Optimierungen beim Datenbankzugriff ausgegangen sind.

Die Klasse, die die Verbindung zur Datenbank hält, sieht bei mir folgendermaßen aus:

public class DB
{
  public string ConnectionString { get; set; } 
  private IDbConnection dbConnection;
  public IDbConnection DbConnection
  {
    get
    {
      if (dbConnection == null)
        dbConnection = new OleDbConnection(ConnectionString);
      if (dbConnection.State == ConnectionState.Closed 
            || dbConnection.State == ConnectionState.Broken)
        dbConnection.Open();
      return dbConnection;
    }
  }
  public DB(string ConnectionString)
  {
    this.ConnectionString = ConnectionString;
  } 
  public void Open()
  {
    dbConnection = new OleDbConnection(ConnectionString);
  } 
  public void Close()
  {
    if (dbConnection != null)
    {
      dbConnection.Close();
      dbConnection.Dispose();
    }
  }
}

Wichtig ist hier die Eigenschaft DbConnection. Diese instanziert die Datenbankverbindung erst wenn sie das erste mal benötigt wird. Falls keine Connection benötigt wird, enthält diese Klasse nichts anderes als einen Connection String. Das ist auch deswegen von Vorteil, da im IIS7 (IMHO nur im Integrated Pipeline Mode) und im Development Webserver des Visual Studio jeder Request (auch Bilder, CSS und JavaScripts) die Event Handler Application_BeginRequest und Application_EndRequest auslöst. Es wird also somit nicht bei jedem Request eine Datenbankverbindung geöffnet.

So sehen die Event Handler in der Global.asax aus:

void Application_BeginRequest(object sender, EventArgs e)
{
  DB db = new DB(ConfigurationManager.ConnectionStrings
        ["DefaultConnection"].ConnectionString);
  HttpContext.Current.Items["DB"] = db;

void Application_EndRequest(object sender, EventArgs e)
{
  DB db = HttpContext.Current.Items["DB"] as DB;
  if (db != null)
    db.Close();
}

In meine Basisklassen habe ich nun ebenfalls einen neue Eigenschaft eingefügt, welche mir die Datenbankverbindung aus dem HttpContext holt:

private DB db;
public IDbConnection DbConnection
{
  get
  {
    if (db == null)
      db = Context.Items["DB"] as DB;
    return db.DbConnection;
  }
}

Meine Datenbankabfragen kann ich somit nun um ein paar Zeilen erleichtern:

string cmdText = "DELETE FROM [emails] WHERE [mailid]=?"
using (OleDbCommand cmd = 
    new OleDbCommand(cmdText, this.DbConnection as OleDbConnection)) 

  cmd.Parameters.Add("mailid", OleDbType.Guid).Value = ID; 
  cmd.ExecuteNonQuery(); 
}

Nachdem ich das nun komplett in meine Anwendung integriert hatte, waren schon alleine beim Durchklicken eine deutliche Verbesserungen der Performance zu spüren.

Peter hatte in dem Thread zusätzlich den Vorschlag gemacht die Methode so weit zu verfeinern, dass nur Page Handler, bzw. Handler dessen Dateiendung "*.aspx" ist. die Klasse für die DB Verbindung instanzieren dürfen. Er geht sogar soweit, die Instanzierung auch für HttpHandler zu erlauben, die ein spezielles Marker Interface implementiert haben.

Das sieht dann so aus, dass erst ein Marker Interface definiert werden muss:

public interface IRequiresDbConnection{}

Die Implementierung des Interfaces:

public partial class myhandler : IHttpHandler, IRequiresDbConnection
{
[...]
}

Da die Handler bei Application_BeginRequest noch null sind, muss die Instanzierung unserer Klasse und die Abfrage auf den Handler, z. B: im Event Handler Application_PreRequestHandlerExecute erfolgen:

void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
  IHttpHandler handler = (sender as HttpApplication).Context.CurrentHandler;
  if (handler != null && (handler is Page || handler is IRequiresDbConnection))
  {
    DB db = new DB(ConfigurationManager.ConnectionStrings
        ["DefaultConnection"].ConnectionString);
    HttpContext.Current.Items["DB"] = db;
  }
}

Da ich die eigentliche Verbindung nur öffne, wenn sie das erste mal benötigt wird und im Prinzip jedes Webform und jeder Generic Handle allein wegen der Authentifizierung eine Datenbankverbindung benötigt, halte ich es in - meinem Fall - nicht für erforderlich Peters Vorschlag mit dem Marker Interface zu arbeiten.

Wie bereits erwähnt, ist in einer Anwendung mit vielen Datenbankzugriffen eine deutliche Performancesteigerung zu spüren, wenn pro Request nur eine Verbindung zur Datenbank geöffnet wird.

Danke euch beiden (Stefan und Peter) für den wertvollen Tipp :-)

Performance Tipp: Eine DB Connection global für einen Page Request definieren.

16.05.2008 23:31:00 | Jürgen Gutsch

Im Moment arbeite ich gerade an einer kleinen Communitiy Anwendung (ja klein, muss ja nicht immer groß sein) die standardmäßig eine Access Datenbank nutzt. Datenbankzugriffe sehen im Moment so aus, dass ich für jede Abfrage eine neue Datenbankverbindung öffne und anschließend wieder schließe. Eigentlich eine normale Prozedur:

using (OleDbConnection conn = new OleDbConnection(this.ConnectionString))
{
  string cmdText = "DELETE FROM [emails] WHERE [mailid]=?";
  using (OleDbCommand cmd = new OleDbCommand(cmdText, conn))
  {
    cmd.Parameters.Add("mailid", OleDbType.Guid).Value = ID;
    cmd.ExecuteNonQuery();
  }
}

Und ausreichend für einen einzelnen Zugriff. Meine Anwendung macht aber pro Page Request mindestens fünf Zugriffe; im Schnitt sind es sogar mehr.

In einem Thread auf MyCSharp, in dem es um zu schließende Connections beim Verlassen einer Website ging, wurde ich von Peter auf eine Diskussion auf Google Groups aufmerksam gemacht, in der es darum ging Datenbankverbindungen global zur Verfügung zu stellen. Stefan stellte dabei einen interessanter Ansatz vor:

Er definierte eine Klasse, die für das Öffnen und Schließen der Datenbankverbindung zuständig ist und die offne Verbindung hält. Diese Klasse wird in der Global.asax bei Application_BeginRequest instanziert, die Connection wird geöffnet und anschließend wird das erzeugte Objekt im aktuellen HttpContext gespeichert. Bei Application_EndRequest wird das Objekt aus dem HttpContext ausgelesen und die Verbindung geschlossen. Im Prinzip eine einfache und geniale Lösung. Die Connection kann jetzt überall in der Anwendung aus dem HttpContext geholt und genutzt werden.

Da ich wie erwähnt nach Optimierungsmöglichkeiten suchte, lag es nahe Stefans Vorschlag auszuprobieren, zumal mir langsam die Ideen für weitere Optimierungen beim Datenbankzugriff ausgegangen sind.

Die Klasse, die die Verbindung zur Datenbank hält, sieht bei mir folgendermaßen aus:

public class DB
{
  public string ConnectionString { get; set; } 
  private IDbConnection dbConnection;
  public IDbConnection DbConnection
  {
    get
    {
      if (dbConnection == null)
        dbConnection = new OleDbConnection(ConnectionString);
      if (dbConnection.State == ConnectionState.Closed 
            || dbConnection.State == ConnectionState.Broken)
        dbConnection.Open();
      return dbConnection;
    }
  }
  public DB(string ConnectionString)
  {
    this.ConnectionString = ConnectionString;
  } 
  public void Open()
  {
    dbConnection = new OleDbConnection(ConnectionString);
  } 
  public void Close()
  {
    if (dbConnection != null)
    {
      dbConnection.Close();
      dbConnection.Dispose();
    }
  }
}

Wichtig ist hier die Eigenschaft DbConnection. Diese instanziert die Datenbankverbindung erst wenn sie das erste mal benötigt wird. Falls keine Connection benötigt wird, enthält diese Klasse nichts anderes als einen Connection String. Das ist auch deswegen von Vorteil, da im IIS7 (IMHO nur im Integrated Pipeline Mode) und im Development Webserver des Visual Studio jeder Request (auch Bilder, CSS und JavaScripts) die Event Handler Application_BeginRequest und Application_EndRequest auslöst. Es wird also somit nicht bei jedem Request eine Datenbankverbindung geöffnet.

So sehen die Event Handler in der Global.asax aus:

void Application_BeginRequest(object sender, EventArgs e)
{
  DB db = new DB(ConfigurationManager.ConnectionStrings
        ["DefaultConnection"].ConnectionString);
  HttpContext.Current.Items["DB"] = db;

void Application_EndRequest(object sender, EventArgs e)
{
  DB db = HttpContext.Current.Items["DB"] as DB;
  if (db != null)
    db.Close();
}

In meine Basisklassen habe ich nun ebenfalls einen neue Eigenschaft eingefügt, welche mir die Datenbankverbindung aus dem HttpContext holt:

private DB db;
public IDbConnection DbConnection
{
  get
  {
    if (db == null)
      db = Context.Items["DB"] as DB;
    return db.DbConnection;
  }
}

Meine Datenbankabfragen kann ich somit nun um ein paar Zeilen erleichtern:

string cmdText = "DELETE FROM [emails] WHERE [mailid]=?"
using (OleDbCommand cmd = 
    new OleDbCommand(cmdText, this.DbConnection as OleDbConnection)) 

  cmd.Parameters.Add("mailid", OleDbType.Guid).Value = ID; 
  cmd.ExecuteNonQuery(); 
}

Nachdem ich das nun komplett in meine Anwendung integriert hatte, waren schon alleine beim Durchklicken eine deutliche Verbesserungen der Performance zu spüren.

Peter hatte in dem Thread zusätzlich den Vorschlag gemacht die Methode so weit zu verfeinern, dass nur Page Handler, bzw. Handler dessen Dateiendung "*.aspx" ist. die Klasse für die DB Verbindung instanzieren dürfen. Er geht sogar soweit, die Instanzierung auch für HttpHandler zu erlauben, die ein spezielles Marker Interface implementiert haben.

Das sieht dann so aus, dass erst ein Marker Interface definiert werden muss:

public interface IRequiresDbConnection{}

Die Implementierung des Interfaces:

public partial class myhandler : IHttpHandler, IRequiresDbConnection
{
[...]
}

Da die Handler bei Application_BeginRequest noch null sind, muss die Instanzierung unserer Klasse und die Abfrage auf den Handler, z. B: im Event Handler Application_PreRequestHandlerExecute erfolgen:

void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
  IHttpHandler handler = (sender as HttpApplication).Context.CurrentHandler;
  if (handler != null && (handler is Page || handler is IRequiresDbConnection))
  {
    DB db = new DB(ConfigurationManager.ConnectionStrings
        ["DefaultConnection"].ConnectionString);
    HttpContext.Current.Items["DB"] = db;
  }
}

Da ich die eigentliche Verbindung nur öffne, wenn sie das erste mal benötigt wird und im Prinzip jedes Webform und jeder Generic Handle allein wegen der Authentifizierung eine Datenbankverbindung benötigt, halte ich es in - meinem Fall - nicht für erforderlich Peters Vorschlag mit dem Marker Interface zu arbeiten.

Wie bereits erwähnt, ist in einer Anwendung mit vielen Datenbankzugriffen eine deutliche Performancesteigerung zu spüren, wenn pro Request nur eine Verbindung zur Datenbank geöffnet wird.

Danke euch beiden (Stefan und Peter) für den wertvollen Tipp :-)

Rosario Talk in der User Group Ulm

15.05.2008 12:39:26 | Christian Binder

Ich werde am 28.5 in der User Group Ulm über Rosario CTP 12 sprechen.
Wir werden den CTP 12 mal genauer unter die Lupe nehmen und die Neuerungen aufzeigen, die jetzt schon drin sind.
Vor allem in der Architekt Edition hat sich viel bewegt: Use Case Diagrams, Sequence Diagrams und  Logical Class Diagrams. Aber auch Neuerungen wie Workitem Links/Hierarchien, UI Testing, Build, Standalone Debugger, Unit Test Impact....  werden ein Thema sein.

Schon heute wissen was morgen passiert :-) dann geht's hier weiter.

Viel Spass

Chris

Windows XP Service Pack 3 (SP3)

15.05.2008 10:02:00 | Ozgur Aytekin

Windows XP Service Pack 3 (SP3) kann unter folgende URL heruntergeladen werden:

Die deutsche Version: Windows XP Service Pack 3-Netzwerkinstallationspaket für IT-Spezialisten und Entwickler

English version: Windows XP Service Pack 3 Network Installation Package for IT Professionals and Developers

Die ISO-Dateien sind wie folgt verfügbar:

Die deutsche Version: Windows XP Service Pack 3 - ISO-9660-CD-Abbilddatei

English version: Windows XP Service Pack 3 - ISO-9660 CD Image File

Wöchentliche Rundablage: ASP.NET MVC, Silverlight 2, TDD, WPF, jQuery…

14.05.2008 13:48:50 | Robert Mühsig

Etwas spät zwar, aber hier eine neue Linkliste der vergangen Woche:

ASP.NET MVC:

TDD / .NET / Development:

Silverlight 2:

ASP.NET:

WPF:

Javascript:

Live Mesh:

Blogging:

Windows SharePoint Services 3.0 Tools: Visual Studio 2005 Extensions User Guide, Version 1.1

13.05.2008 21:00:00 | Ozgur Aytekin

Die Version 1.1 des "User Guide for the Visual Studio 2005 extensions for Windows SharePoint Services 3.0" wurde veröffentlicht.

Dieser Bedienungsanleitung beinhaltet folgende Themen:

  • Starting out in SharePoint Development
  • Walkthrough of the VSeWSS User Interface including the WSP View
  • The Team Site Project
  • The Blank Site Project
  • The List Definition Project
  • The Web Part Project
  • The Workflow Projects
  • Project Item Templates
  • Best Practices with VSeWSS
  • Changes from 1.0 to 1.1

Die URL für die Installationsdatei ist wie folgt: Windows SharePoint Services 3.0 Tools: Visual Studio 2005 Extensions User Guide, Version 1.1

Visual Studio 2008 and .NET Framework 3.5 Service Pack 1 Beta

13.05.2008 20:51:00 | Ozgur Aytekin

Microsoft hat die Public Beta 1 Version von Visual Studio 2008 und .NET Framework 3.5 Service Pack veröffentlicht.

Dieser Version soll nicht auf produktiven Maschinen installiert werden.

Wegen bekannten Installationsfehler, darf dieser Service Pack 1 Beta Version auf Vista Rechner mit Service Pack 1 installiert werden. Dieser Fehler wird in der Final-Version behoben sein, meldet ScottGu in seinem Blog.

Für weitere Informationen zum Thema "Wichtige Installations-Notizen" folgenden Blog-Eintrag lesen.

Important: SP1 Beta Installation Notes

Die wichtigsten Verbesserungen im Bereich Web Entwicklung sind:

  • ASP.NET Data Scaffolding Support (ASP.NET Dynamic Data
  • ASP.NET Routing Engine (System.Web.Routing)
  • ASP.NET AJAX Back/Forward Button History Support
  • ASP.NET AJAX Script Combining Support
  • Visual Studio 2008 Performance Improvements HTML Designer and HTML Source Editor
  • Visual Studio 2008 JavaScript Script Formatting and Code Preferences
  • Better Visual Studio Javascript Intellisense for Multiple Javascript/AJAX Frameworks
  • Visual Studio Refactoring Support for WCF Services in ASP.NET Projects
  • Visual Studio Support for Classic ASP Intellisense and Debugging
  • Visual Web Developer Express Edition support for Class Library and Web Application Projects

Im Bereich Client Entwicklung sind:

  • Application Startup and Working Set Performance Improvements
  • New .NET Framework Client Profile Setup Package
  • New .NET Framework Setup Bootstrapper for Client Applications
  • ClickOnce Client Application Deployment Improvements
  • Windows Forms Controls
  • WPF Performance Improvements
  • WPF Data Improvements
  • WPF Extensible Shader Effects
  • WPF Interoperability with Direct3D
  • VS 2008 for WPF Improvements

In dieser Version wird auch das ADO.NET Entity Framework and LINQ to Entities mitgeliefert.

Unter anderem im Bereich Daten sind folgende Verbesserungen vorhanden:

  • SQL 2008 Support
  • ADO.NET Entity Framework and LINQ to Entities
  • ADO.NET Data Services (formerly code-named "Astoria")

Auch für Team Foundation Server (TFS) kommen viele Verbesserungen mit. Für eine detailierte Information hat Brian Harry in sein Blog folgenden Artikel geschrieben: Team Foundation Server 2008 SP1 Preview

Die URLs für den Download findet ihr auf der folgende Seite: Visual Studio 2008 and .NET Framework 3.5 Service Pack 1 Beta

Für detaillierte Informationen kann ich euch folgende URLs empfehlen:

MSDN: Visual Studio 2008 and .NET Framework 3.5 Service Pack 1 Beta

ScottGu’s Blog: Visual Studio 2008 and .NET Framework 3.5 Service Pack 1 Beta

Brian Harry's WebLog:Team Foundation Server 2008 SP1 Preview

KB 946581 - Visual Studio 2008 - Hotfix

13.05.2008 19:41:00 | Ozgur Aytekin

Microsoft hat ein kumulatives Update für Microsoft Visual Studio 2008 und Microsoft Visual Web Developer 2008 zur Verfügung gestellt.

Dieser Hotfix ist nicht sehr neu, aber irgendwie wenig bekannt unter den Visual Studio 2008 Entwickler.

In diesem Hotfix sind unter anderem folgende Punkte verbessert:

  • Bugs in HTML Source View performance
  • Bug in Design view performance
  • Bugs in HTML editing
  • Bugs in JavaScript editing
  • Bugs in Web site building performance
  • Hotfix information

Weitere und detailierte Informationen findet ihr unter: A cumulative update for Visual Studio 2008 and Visual Web Developer Express 2008 is available

Die Datei findet ihr unter: Download

fmx & Silverlight

13.05.2008 17:29:00 | Lori Grosland

Vom 5. – 8. Mai fand in Stuttgart die 13. fmx Konferenz statt – Europas größte Konferenz zum Thema Animationen, Effekte, Games und Digital Media – veranstaltet von der Filmakademie Baden Württemberg. Microsoft war zum ersten Mal als einer der Hauptsponsoren mit einem großen Stand und einer Xbox-Lounge vertreten, an der sich die Besucher mit einer Tüte Popcorn bei Guitar Hero und anderen Xbox-Spielen vom Konferenzstress erholen konnten. Am Stand präsentierte Microsoft dem interessierten Publikum aus der Games-, Medien- und Designbranche neue Technologien wie  Microsoft Silverlight, Microsoft Popfly und Microsoft Live Labs Photosynth.

 

Ich war dabei und habe vor Ort mit Steffen Ritter, Microsoft Designer Marketing Manager über alles rund um die fmx und natürlich auch über sein Lieblings-Thema Silverlight gesprochen.  Auch zu sehen in diesem Video, ein paar coole Silverlight Demos, vorgestellt von Oliver Scheer, Microsoft Developer Evangelist.

 

Die Demos findet man auch hier:

http://silverlight.net/themes/silverlight/community/gallerydetail.aspx?cat=5
http://silverlight.idvsolutions.com/
http://memorabilia.hardrock.com/
http://www.bluerosegames.com/brg/games.aspx
http://home.comcast.net/~barney.ross/RubikCube/RubikCubeTestPage.html
http://silverlight.net/

Microsoft Expression Studio 2 ist hier...

11.05.2008 22:12:00 | Ozgur Aytekin

Die englische Version des Microsoft Expression 2 Tools ist veröffentlicht.

Die Trial Versionen können unter folgende URL heruntergeladen werden: Try Expression Products

Wer die Microsoft Expression 1 Produkte zwischen 24.02.2008 und 01.06.2008 gekauft hat, ist für einen Gratis (Free) Upgrade des gleichen Produktes berechtigt. Die detailierte Informationen findet ihr unter folgende URL: Upgrade Eligibility

Microsoft SQL Server 2008 CTP Unterstützung für Visual Studio 2005 und Visual Studio 2008

11.05.2008 21:23:00 | Ozgur Aytekin

SQL Server 2008 CTP Unterstützung für Visual Studio 2005 kann unter folgende URL heruntergeladen werden: Visual Studio 2005 Support for SQL Server 2008 CTP

Für die Einschränkungen und bekannte Fehler (Known Issues) bitte die Informationen auf der Downlad-Seite lesen.

SQL Server 2008 CTP Unterstützung für Visual Studio 2008 kann unter folgende URL heruntergeladen werden: Visual Studio 2008 Support for SQL Server 2008 CTP

Leider Unterstützt dieser Version den LINQ to SQL Designer mit SQL Server 2008 noch nicht.

Auch bei dieser Download, für die Einschränkungen und bekannte Fehler (Known Issues) bitte die Informationen auf der Download-Seite lesen.

Für Allgemeine Informationen über die SQL Server 2008 CTP Unterstützung kann ich Euch folgende Seite empfehlen: Connecting to Microsoft SQL Server 2008 from Microsoft Visual Studio 2005 and 2008

KB 951937 – Funktionalitätsproblem mit ActiveX Data Objects (ADO)

11.05.2008 17:18:00 | Ozgur Aytekin

Für Entwickler, die für Windows Vista, Windows Server 2008 oder Windows XP Anwendungen entwickeln und die ActiveX Data Objects (ADO)-Schnittstelle mit SQL Server 2000 oder SQL Server 2005 einsetzen kann folgender KB Artikel mit der Nummer 951937 von Microsoft interessant sein: "On a computer that is running Windows Vista, Windows Server 2008, or Windows XP, an incorrect value is returned when an application queries the identity column value of a newly inserted row in various versions of SQL Server 2005 and of SQL Server 2000"

Weitere Informationen findet ihr unter folgende URL: KB 951937

Die let-Klausel (clause) in LINQ

11.05.2008 15:01:00 | Ozgur Aytekin

Für die Erstellung einer temporären Variable innerhalb einer Query Expression kann das Schlüsselwort let verwendet werden. Mithilfe einer Formel wird an diese Variable ein neuer Wert aus bestehenden Daten zugewiesen. Die Variable ist dann innerhalb der Query Expression weiterverwendet und bei Bedarf im Select-Block ausgegeben werden.

Die Lesbarkeit des Codes wird durch die Verwendung von Schlüsselwort let gesteigert und der Code bleibt übersichtlich.

In dem folgenden Beispiel werden mithilfe des let-Schlüsselwortes zwei Variablen (DistributorPrice und ProductColorIsBlack) erstellt.

Die Variable DistributorPrice beinhaltet den Wert des Händlerpreises. Dieser Preis wird mithilfe des Faktors 0.75 vom Listenpreis berechnet.
let DistributorPrice = (p.ListPrice*Convert.ToDecimal(0.75))

Die Variable ProductColorIsBlack beinhaltet den Wert, ob die Produktfarbe Schwarz ist.
let ProductColorIsBlack = (p.Color != null && p.Color == "Black")                   

Innerhalb des Select-Blocks werden die beiden Variablen ausgegeben.
select new
{
   ProductCategoryName = pc.Name,
   ProductSubCategoryName = psc.Name,
   ProductName = p.Name,
   p.ListPrice,
   DistributorPrice,
   ProductColorIsBlack
};

Der gesamte Beispiel Code ist wie folgt aufgelistet:



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->using System;
using System.Linq;

namespace LinqLetSample0001
{
internal class Program
{
private static void Main(string[] args)
{
var db
= new AdventureWorksDataContext();

var qry
= from pc in db.ProductCategories
join psc
in db.ProductSubcategories on pc.ProductCategoryID equals psc.ProductCategoryID
join p
in db.Products on psc.ProductSubcategoryID equals p.ProductSubcategoryID
let DistributorPrice
= (p.ListPrice * Convert.ToDecimal(0.75))
let ProductColorIsBlack
= (p.Color != null && p.Color == "Black")
select
new
{
ProductCategoryName
= pc.Name,
ProductSubCategoryName
= psc.Name,
ProductName
= p.Name,
p.ListPrice,
DistributorPrice,
ProductColorIsBlack
};

foreach (var item in qry)
{
Console.WriteLine(
"Product Category : " + item.ProductCategoryName);
Console.WriteLine(
"Product Sub Category : " + item.ProductCategoryName);
Console.WriteLine(
"Product : " + item.ProductName);
Console.WriteLine(
"Product Distributor Price: " + item.DistributorPrice);
Console.WriteLine(
"Product List Price : " + item.ListPrice);
Console.WriteLine(
"Product Color is Black : " + item.ProductColorIsBlack);
Console.WriteLine();
}

Console.ReadLine();
}
}
}


Das komplette Visual Studio 2008 Projekt kann unter folgende URL heruntergeladen werden: LinqLetSample0001.zip






 


Simples Text Captcha mit ASP.NET

11.05.2008 01:56:00 | Peter Bucher

Es gibt viele Captcha Controls im Web zu finden.
Trotzdem möchte ich hier eine einfache Variante vorstellen.
Diese Variante benutzt ein Label, um eine Rechnung darzustellen, bspw. "5 + 6 =".
Eine Textbox fürs Resultat, ein Button und ein Statuslabel wir im Beispiel verwendet.

Ich benutze einen ähnlichen Code auf http://www.peterbucher.ch/, bis jetzt habe ich noch nie Spam bekommen :)

Viel Spass damit...

ASPX Code:

<h1>SimpleCaptcha</h1>
<asp:Label ID="lblCaptcha" AssociatedControlID="txtCaptcha" runat="server" />
<asp:TextBox ID="txtCaptcha" runat="server" />
<asp:Button ID="btnSubmit" Text="Abschicken" runat="server" />
<asp:Label ID="lblStatus" runat="server" />

Codebehind:

using System;
using System.Drawing;


namespace WebApplication1
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e) {
            // Textbox Inhalt zuweisen
            // Resultat in die Session Speichern
            if(!this.IsPostBack) {
                Random r = new Random();
                int num1   = r.Next(1, 15);
                int num2   = r.Next(1, 15);

                this.lblCaptcha.Text = string.Format("{0} + {1} =",
                                                     num1.ToString(),
                                                     num2.ToString());

                this.Session["captcha"] = num1 + num2;
            } else {
                // Status anzeigen
                if(this.ValidateCaptcha()) {
                    this.lblStatus.Text         = "Eingabe korrekt";
                    this.lblStatus.ForeColor = Color.Green;
                } else {
                    this.lblStatus.Text         = "Eingaben fehlerhaft";
                    this.lblStatus.ForeColor = Color.Red;
                }
            }
        }

        /// <summary>
        /// Validiert die Eingabe
        /// </summary>
        /// <returns>true / false - Eingabe richtig oder falsch</returns>
        protected bool ValidateCaptcha() {
            object session = this.Session["captcha"];
            object input     = this.txtCaptcha.Text;

            if(session != null && input != null) {
                int s, i;
                return (int.TryParse(session.ToString(), out s)
                        &&
                        int.TryParse(input.ToString(), out i)
                        && s.Equals(i));
            }

            return false;
        }
    }
}

Beispielprojekt zum Download:

Der Trend geht zum zweit-iPod

09.05.2008 18:54:15 | Oliver Guhr

…zumindest wenn es nach Amazon geht. Als ich heute mal wieder beim Internet Gemischtwarenladen vorbeischaute war ich erstaunt amüsiert was mir am neuen Produkten empfohlen wurde. Das solche automatischen Produktvorschläge fast nie sinnvolle Ergebnisse liefern ist ja bekannt, bei Amazon kann man sich sogar anschauen warum der Artikel vorgeschlagen wurde:

amazon

Weil ich einen iPod + Tasche erstanden habe könnte mir der 80 GB iPod auch gefallen - tut er auch, kaufen werde ich ihn aber nicht.

Visual Studio Extensibility Event am 26 Mai

09.05.2008 16:15:53 | Christian Binder

wer einen Überblick zu den Erweiterungsmöglichkeiten von Visual Studio sucht, sollte sich dieses Event nicht entgehen lassen. Bauen Sie z.B. Ihre Application auf Basis der Visual Studio Shell.
Inhaltlich werden folgende Themen von Ken Levy, Program Manager Visual Studio, behandelt:

  • Visual Studio Shell
  • Visual Studio SDK
  • Erweiterung von Visual Studio wie
    • Packages,
    • Add-Ins,
    • Makros und
    • Visualizer

    Anmeldung hier 

    Hinweis: Die Veranstalltung ist in Englischer Sprache und es gibt maximal 20 Plätze.

    Chris

    XNA Game Studio 3.0 CTP: Endlich VS 2008 & .NET 3.5

    08.05.2008 23:46:32 | Robert Mühsig

    image

    Für alle die, die sich für “Spieleentwicklung” interessieren gibt es nun ein neu Version (CTP) vom XNA Game Studio:

    Es integriert sich in Visual Studio 2008 - von der Express bis zu den Prof. und bietet .NET 3.5 Unterstützung.

    Hier die komplette Ankündigung von Microsoft und der Download Link.

    TDD, Unit-Tests & XNA \o/ :)

    Wer ist unter uns oder whos.amung.us

    08.05.2008 14:30:12 | Oliver Guhr

    Durch einfaches einbinden eines kleinen Buttons von whos.amung.us kann man sehen wer gerade den eigenen Blog durchstöbert und wo die Leute so herkommen. Zur auswahl gibts schicke Karten, z.b.

    Besucherkarte

    Besucherkarte

    Die Aktuellen Karten für code-inside.de kann man hier finden, der Button auf code-inside ist rechts oben unter “Counter”.

    Meine Vorträge demnächst zu Silverlight

    06.05.2008 19:00:32 | Mario Meir-Huber

    In nächster Zeit bin ich viel unterwegs und werde den einen oder anderen Vortrag zum Thema Silverlight halten. Der erste wird am 27. Mai in Linz, Oberösterreich sein. Dort geht es vor allem um die Neuerungen im Bereich Silverlight 2.0.

    Eine genauere Beschreibung ist auf der Usergroup Seite vorhanden: http://usergroups.at/blogs/netlinz/default.aspx

    Im Juni bin ich dann in Burghausen auf der Asp.Net Konferenz, wo ich 3 Vorträge zum Thema Silverlight halten werde. Diese sind:

    - Silverlight auf mobilen Geräten

    - Silverlight am Sharepoint Portal Server

    - ChartLibrary für Silverlight

     

    Infos gibt es hierfür unter: http://www.asp-konferenz.de

    Live Übertragung des Treffen der .net user group Köln am 6. Mai 2008 (heute)

    06.05.2008 15:25:06 | Albert Weinert

    Hallo zusammen,

    die .net user group Köln plant heute Abend ein experiment. Wir wollen unser Usertreffen live im Internet streamen. So dass auch die Leute die nicht um Köln herum wohnen die Möglichkeit haben daran teilzunehmen.

    Die Sende-Adresse ab 19 Uhr ist

    http://www.mogulus.com/dnugkoeln

    Wir wissen noch nicht ob und wie es klappt (Bandbreite, Licht etc.), also  erscheint ruhig zahlreich und tragt bitte einen ordentlichen Nickname für den Chat ein.

    Die Themen heute sind

    Final Builder 6
    Robert Wachtel

    Final Builder ist ein Build-Werkzeug mit dem man seine Software-Builds automatisieren kann. Von einfacher Automatisierung bis zum CI-Server ist alles damit machbar. Sowohl auf dem Client als auch dem Server. Robert Wachtel gibt einen Überblick über die Möglichkeiten.

    ADO.NET „Astoria“ Data Services
    Albert Weinert


    Mit .NET 3.5 Service Pack 1 kommen die ADO.NET Data Services in das .NET Framework, aktuell gibt es sie als Preview zum runterladen und ausprobieren. Mit den Data Services wird eine REST basierte Schnittzustelle zu beliebigen Daten ermöglicht. Damit werden über das HTTP Protokoll Daten für JavaScript, Silverlight und Fat-Client Anwendungen ermöglicht. CRUD-Operationen sind natürlich auch möglich.

    http://www.dnug-koeln.de

     

    Wöchentliche Rundablage: ASP.NET MVC, Live Mesh, Silverlight, .NET…

    05.05.2008 22:22:53 | Robert Mühsig

    ASP.NET MVC:

    Live Mesh:

    .NET Framework:

    WPF / Silverlight:

    UI / Design:

    LINQ:

    Virtual Earth:

    Other:

    Software-Tipp: Microsoft SharedView - "Welchen Knopf muss ich denn drücken?"

    05.05.2008 20:47:27 | Robert Mühsig

    Die Frage “Welchen Knopf muss ich denn drücken?” oder ähnliche sind meist recht schwer zu beantworten. Ferndiagnosen sind meist recht schwer zu bewältigen.

    Seit einer Weile hat Microsoft ein nettes Tool - ganz ohne jeden großen Rummel - veröffentlicht: SharedView.

    image

    SharedView erlaubt es einfach den Desktop zu teilen oder nur eine einzelne Applikation mit bis zu 15 Leuten. Das ganze läuft auf Port 80 - daher ist keine Portfreischaltung notwendig.

    Einmal installiert (mit Adminrechten) muss man sich mit seiner Windows Live ID anmelden und kann eine Session aufbauen oder einer Session beitreten.

    Um mal der Freundin zu helfen ist es genial ;)

    jQuery… ein paar Links

    05.05.2008 20:14:08 | Robert Mühsig

    Da ASP.NET AJAX und ASP.NET MVC (noch?) nicht so richtig gut zusammenpassen muss ganz klar eine andere Javascript Bibliothek und AJAX Framework her - jQuery hat es mir angetan.

    Der Blogpost ist eher eine Zusammenfassung von den Links die ich in den letzten Rundablagen bereits nebenbei gebloggt hab.

    Was gibt es denn sonst noch für Javascript-Bibliotheken?

    Danny Douglass hat einen netten Vergleich zwischen jQuery, YUI, Prototype, Dojo, MooTools, Ext JS, und Script.aculo.us gemacht. Eine nette Auflistung der Merkmale findet man hier.

    jQuery Beispiele und Tutorials?

    Auf noupe.com gefunden:

    Drag`n`Drop gibts auch:

    Es gibt noch mehr tolle Beispiele (siehe links oben), eine aktuelle offline Dokumentation hab ich zwar noch nicht gefunden, aber für die Version 1.1.4 gibt es hier eine.

    Jeder braucht Plugins… jQuery hat einige:

    Auf noupe.com gefunden:

    VS 2008 / ASP.NET Integration:

    Wer noch mehr brauchbare Links kennt, einfach kurz melden :)

    Übersicht der DateTime-Datentypen in SQL Server 2008

    04.05.2008 17:24:00 | Ozgur Aytekin

    Der folgende Artikel gibt einen Übersicht über die DateTime-Datentypen in SQL Server 2008. Auch die neuen Datentypen wie DATE, DATETIME2, DATETIMEOFFSET, und TIME sind in diesem Artikel beschrieben.

    DATE - NEU

    Der Datentyp DATE speichert Datumswert ohne Zeit Informationen.

    Der Bereich für diesen Datentyp liegt zwischen 0001-01-01 - 9999-12-31 (Jahr - Monat -Tag).

    Der Speicherbedarf liegt bei 3 bytes.



    Code highlighting produced by Actipro CodeHighlighter (freeware)
    http://www.CodeHighlighter.com/

    --> 1 -- DATE --------------------------------------
    2 -- Format : Jahr - Monat - Tag
    3 -- Year - Month - Day
    4
    5 -- Range : 0001-01-01 - 9999-12-31
    6 -- Storage Size : 3 bytes
    7 -- Default value: 1900-01-01
    8 ----------------------------------------------
    9
    10 -- Beispiel-Code -----------------------------
    11 DECLARE @Date_DataType DATE
    12 SET @Date_DataType = SYSDATETIME()
    13
    14 PRINT SYSDATETIME()
    15 PRINT @Date_DataType
    16 ----------------------------------------------
    17
    18 -- Resultat ----------------------------------
    19 -- SYSDATETIME() : 2008-05-04 16:54:59.0370304
    20 -- @Date_DataType: 2008-05-04
    21 ----------------------------------------------
    22


    DATETIME



    Der Datentyp DATETIME speichert Datum und Zeit Informationen.



    Der Bereich für diesen Datentyp liegt zwischen 1753-01-01 00:00:00 - 9999-12-31 23:59:59.997 (Jahr - Monat - Tag Stunden : Minuten : Sekunden .Sekundenbruchteile).



    Die Genauigkeit der Sekundenbruchteile kann bei diesem Datentyp nicht festgelegt werden.



    Der Speicherbedarf liegt bei 8 bytes.





    Code highlighting produced by Actipro CodeHighlighter (freeware)
    http://www.CodeHighlighter.com/

    --> 1 -- DATETIME --------------------------------------------------------------------------
    2 -- Format : Jahr - Monat - Tag Stunden : Minuten : Sekunden .Sekundenbruchteile
    3 -- Year - Month - Day Hours : Minutes : Seconds .Fractional Seconds
    4
    5 -- Range : 1753-01-01 00:00:00 - 9999-12-31 23:59:59.997
    6 -- Storage Size : 8 bytes
    7 -- Default value: 1900-01-01 00:00:00
    8 ---------------------------------------------------------------------------------------
    9
    10 -- Beispiel-Code ----------------------------------------------------------------------
    11 DECLARE @DateTime_DataType DATETIME
    12 SET @DateTime_DataType = SYSDATETIME()
    13
    14 PRINT SYSDATETIME()
    15 PRINT @DateTime_DataType
    16 ---------------------------------------------------------------------------------------
    17
    18 -- Resultat ---------------------------------------------------------------------------
    19 -- SYSDATETIME() : 2008-05-04 16:29:41.1544224
    20 -- @DateTime_DataType: 2008-05-04 16:51
    21 ---------------------------------------------------------------------------------------
    22


    DATETIME2 - NEU



    Als Erweiterung des Datentyps DATETIME, speichert DATETIME2 einen größeren Datumsbereich und eine größere Genauigkeit beim Sekundenbruchteil.



    Der Bereich für diesen Datentyp liegt zwischen 0001-01-01 00:00:00 - 9999-12-31 23:59:59.9999999 (Jahr - Monat - Tag Stunden : Minuten : Sekunden [.Sekundenbruchteile]).



    Die Genauigkeit der Sekundenbruchteile kann beim Deklarieren der Variable festgelegt werden, welches zwischen 0 und 7 sein kann.



    Der Speicherbedarf liegt bei 8 bytes.





    Code highlighting produced by Actipro CodeHighlighter (freeware)
    http://www.CodeHighlighter.com/

    --> 1 -- DATETIME2 ---------------------------------------------------------------------------
    2 -- Format : Jahr - Monat - Tag Stunden : Minuten : Sekunden [.Sekundenbruchteile]
    3 -- Year - Month - Day Hours : Minutes : Seconds [.Fractional Seconds]
    4
    5 -- Range : 0001-01-01 00:00:00 - 9999-12-31 23:59:59.9999999
    6 -- Storage Size : 8 bytes
    7 -- Default value: 1900-01-01 00:00:00
    8 ----------------------------------------------------------------------------------------
    9
    10 -- Beispiel-Code -----------------------------------------------------------------------
    11 DECLARE @DateTime2_DataType DATETIME2(7)
    12 SET @DateTime2_DataType = SYSDATETIME()
    13
    14 PRINT SYSDATETIME()
    15 PRINT @DateTime2_DataType
    16 ----------------------------------------------------------------------------------------
    17
    18 -- Resultat ----------------------------------------------------------------------------
    19 -- SYSDATETIME() : 2008-05-04 16:22:33.6997728
    20 -- @DateTime2_DataType: 2008-05-04 16:22:33.6997728
    21 ----------------------------------------------------------------------------------------
    22


    DATETIMEOFFSET - NEU



    Der Datentyp DATETIMEOFFSET speichert zusätzlich zu den Datumsangaben mit Zeit Informationen auch die Zeitzonen Information.



    Der Bereich für diesen Datentyp liegt zwischen 0001-01-01 00:00:00 - 9999-12-31 23:59:59.9999999 (Jahr - Monat - Tag Stunden : Minuten : Sekunden [.Sekundenbruchteile] [+|- Stunden : Minuten]).



    Die Genauigkeit der Sekundenbruchteile kann beim Deklarieren der Variable festgelegt werden, welches zwischen 0 und 7 sein kann.



    Der Speicherbedarf liegt bei 10 bytes.





    Code highlighting produced by Actipro CodeHighlighter (freeware)
    http://www.CodeHighlighter.com/

    --> 1 -- DATETIMEOFFSET -----------------------------------------------------------------------------------------------
    2 -- Format : Jahr - Monat - Tag Stunden : Minuten : Sekunden [.Sekundenbruchteile] [+|- Stunden : Minuten]
    3 -- Year - Month - Day Hours : Minutes : Seconds [.Fractional Seconds] [+|- Hours : Minutes]
    4
    5 -- Range : 0001-01-01 00:00:00 - 9999-12-31 23:59:59.9999999
    6 -- Storage Size : 10 bytes
    7 -- Default value: 1900-01-01 00:00:00 00:00
    8 -----------------------------------------------------------------------------------------------------------------
    9
    10 -- Beispiel-Code ------------------------------------------------------------------------------------------------
    11 DECLARE @DateTimeOffset_DataType DATETIMEOFFSET(7)
    12 SET @DateTimeOffset_DataType = SYSDATETIME()
    13
    14 PRINT SYSDATETIME()
    15 PRINT @DateTimeOffset_DataType
    16 -----------------------------------------------------------------------------------------------------------------
    17
    18 -- Resultat -----------------------------------------------------------------------------------------------------
    19 -- SYSDATETIME() : 2008-05-04 13:59:59.9918208
    20 -- @DateTimeOffset_DataType: 2008-05-04 13:59:59.9918208 +00:00
    21 -----------------------------------------------------------------------------------------------------------------
    22


    Für die manueller Zuweisung eines Wertes muss ein spezielles Format eingehalten werden. In diesem Format sind die Datumsangaben von den Zeitangaben mit dem Buchstaben „T“ voneinander getrennt. Die Angabe der Zeitzone erfolgt nach Sekundenbruchteile und beginnt mit einem „+“ oder „-„.





    Code highlighting produced by Actipro CodeHighlighter (freeware)
    http://www.CodeHighlighter.com/

    --> 1 -- Beispiel-Code ------------------------------------------------------------------------------------------------
    2 SET @DateTimeOffset_DataType = '2008-05-04T13:59:59.9918208+00:00'
    3
    4 PRINT @DateTimeOffset_DataType
    5 -----------------------------------------------------------------------------------------------------------------
    6
    7 -- Resultat -----------------------------------------------------------------------------------------------------
    8 -- @DateTimeOffset_DataType: 2008-05-04 13:59:59.9918208 +00:00
    9 -----------------------------------------------------------------------------------------------------------------
    10


    Der Format des DATETIMEOFFSET Datentyps entspricht dem ISO 8601.



    ISO 8601 ist ein internationaler Standard der ISO, der numerische Datumsformate und Zeitangaben beschreibt und Empfehlungen für den Gebrauch im internationalen Kontext ausspricht. Der Titel der Norm ist Data elements and interchange formats -- Information interchange -- Representation of dates and times, was im deutschen „Datenelemente und Austauschformate; Informationsaustausch; Darstellung von Datum und Uhrzeit“ bedeutet.



    Quelle: Wikipedia



     



    SMALLDATETIME



    Der Datentyp SMALLDATETIME speichert Datumsangaben mit Zeit Information im 24-Stunden-Format ohne Sekundenbruchteile.



    Der Bereich für diesen Datentyp liegt zwischen 1900-01-01 00:00:00 - 2079-06-06 23:59:59 (Jahr - Monat - Tag Stunden - Minuten – Sekunden).





    Code highlighting produced by Actipro CodeHighlighter (freeware)
    http://www.CodeHighlighter.com/

    --> 1 -- SMALLDATETIME -------------------------------------------------
    2 -- Format : Jahr - Monat - Tag Stunden : Minuten : Sekunden
    3 -- Year - Month - Day Hours : Minutes : Seconds
    4
    5 -- Range : 1900-01-01 00:00:00 - 2079-06-06 23:59:59
    6 -- Storage Size : 4 bytes
    7 -- Default value: 1900-01-01 00:00:00
    8 -----------------------------------------------------------------
    9
    10 -- Beispiel-Code ------------------------------------------------
    11 DECLARE @SmallDateTime_DataType SMALLDATETIME
    12 SET @SmallDateTime_DataType = SYSDATETIME()
    13
    14 PRINT SYSDATETIME()
    15 PRINT @SmallDateTime_DataType
    16 -----------------------------------------------------------------
    17
    18 -- Resultat -----------------------------------------------------
    19 -- SYSDATETIME() : 2008-05-04 13:30:56.9855008
    20 -- @SmallDateTime_DataType: 2008-05-04 13:31
    21 -----------------------------------------------------------------
    22


    Die Minuten werden aufgerundet, wenn die Sekunden größer sind als 29.



     



    TIME - NEU



    Der Datentyp TIME speichert die Zeit ohne Datumsangaben im 24-Stunden-Format.



    Der Bereich für diesen Datentyp liegt zwischen 00:00:00.0000000 und 23:59:59.9999999 (Stunden : Minuten : Sekunden [.Sekundenbruchteile]).



    Die Genauigkeit der Sekundenbruchteile kann beim Deklarieren der Variable festgelegt werden, welches zwischen 0 und 7 sein kann.





    Code highlighting produced by Actipro CodeHighlighter (freeware)
    http://www.CodeHighlighter.com/

    --> 1 -- TIME -----------------------------------------------------------
    2 -- Format : Stunden : Minuten : Sekunden . Sekundenbruchteile
    3 -- Hours : Minutes : Seconds . Fractional Seconds
    4
    5 -- Range : 00:00:00.0000000 - 23:59:59.9999999
    6 -- Storage Size : 3 - 5 bytes
    7 -- Default value: 00:00:00
    8 -------------------------------------------------------------------
    9
    10 -- Beispiel-Code --------------------------------------------------
    11 DECLARE @Time_DataType TIME(7)
    12 SET @Time_DataType = SYSDATETIME()
    13
    14 PRINT SYSDATETIME()
    15 PRINT @Time_DataType
    16 -------------------------------------------------------------------
    17
    18 -- Resultat -------------------------------------------------------
    19 -- SYSDATETIME() : 2008-05-04 13:00:15.0369088
    20 -- @Time_DataType: 13:00:15.0369088
    21 -------------------------------------------------------------------
    22


    Die Beispieldatei findet Ihr unter: DateTime_DataTypes_Sample_0001.sql

    Microsoft SQL Server Product Samples

    04.05.2008 08:29:00 | Ozgur Aytekin

    Unter folgende URL findet Ihr die Beispiel Datenbanken für den Microsoft SQL Server 2008:

    Datenbanken -(Databases)

     

    Die folgende Seite bietet diverse Beispiele zu den Themen:

    - Microsoft Product Samples

    - Sample Databases

    - End to End (multi-technology, complete, integrated)

    - Microsoft SQL Server Analysis Services

    - Microsoft SQL Server Database Engine

    - Microsoft SQL Server Integration Services

    - Microsoft SQL Server Reporting Services

    - Platform Tools & Utilities

    - Forums & Answers

    Microsoft SQL Server Community & Samples

    UNION und UNION ALL

    03.05.2008 23:45:00 | Ozgur Aytekin

    UNION Statement unterdrückt wie bei einem SELECT DISTINCT die doppelten Einträge im Resultat. Von den mehrfach vorkommenden Datensätzen wird nur ein Datensatz im Resultat zurückgegeben.

    Für die Verwendung von UNION und UNION ALL Statements werden mindestens zwei Datenquellen benötigt. Die beiden Datenquellen müssen gleicher Anzahl Spalten (Columns) besitzen. Jeder einzelnen Spalte in der Tabelle 1 muss in der Tabelle 2 mit gleichem Datentyp (data type) vorkommen.

    Für die Verwendung von UNION und UNION ALL Statements werden mindestens zwei Datenquellen benötigt. Die ausgewählten Spalten (Columns) der beiden Datenquellen müssen in gleicher Anzahl vorkommen. Auch die Datentypen (data types) dieser Spalten müssen vom selben Typ sein.

    Im Resultat werden als Spaltennamen die Spaltennamen der ersten Datenquelle verwendet.

    UNION ALL Statement liefert alle Datensätze aus beiden Datenquellen als Resultat zurück. Hier werden die doppelten Einträge nicht unterdrückt und sie werden als ein des Resultates zurückgegeben. Für die Verwendung von UNION ALL Statement gelten die gleichen Bedingungen für die Datenquellen wie beim UNION-Statement.

    Für das Beispiel werden zwei Tabellen mit dem Namen CountryCity und CountryCapital erstellt.



    Code highlighting produced by Actipro CodeHighlighter (freeware)
    http://www.CodeHighlighter.com/

    --> 1
    2 IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[CountryCity]') AND type in (N'U'))
    3 DROP TABLE [dbo].[CountryCity]
    4 GO
    5
    6 IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[CountryCapital]') AND type in (N'U'))
    7 DROP TABLE [dbo].[CountryCapital]
    8 GO
    9
    10 CREATE TABLE [dbo].[CountryCity]([ID] [int] NOT NULL,
    11 [Country] [nvarchar] (50) NOT NULL,
    12 [City] [nvarchar] (50) NOT NULL)
    13
    14 CREATE TABLE [dbo].[CountryCapital]([ID] [int] NOT NULL,
    15 [Country] [nvarchar] (50) NOT NULL,
    16 [City] [nvarchar] (50) NOT NULL)
    17
    18




    In der Tabelle CountryCity befinden die Länder und Städte.





    Code highlighting produced by Actipro CodeHighlighter (freeware)
    http://www.CodeHighlighter.com/

    --> 1 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (1, 'SWITZERLAND', 'ZURICH')
    2 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (2, 'SWITZERLAND', 'BERN')
    3 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (3, 'SWITZERLAND', 'GENEVA')
    4 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (4, 'GERMANY', 'BERLIN')
    5 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (5, 'GERMANY', 'HAMBURG')
    6 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (6, 'GERMANY', 'MUNICH')
    7 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (7, 'AUSTRIA', 'VIENNA')
    8 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (8, 'AUSTRIA', 'GRAZ')
    9 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (9, 'AUSTRIA', 'LINZ')
    10 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (10, 'TURKIYE', 'ISTANBUL')
    11 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (11, 'TURKIYE', 'ANKARA')
    12 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (12, 'TURKIYE', 'IZMIR')


    Die Tabelle CountryCapital beinhaltet die Länder und die Hauptstadt des Landes.







    Code highlighting produced by Actipro CodeHighlighter (freeware)
    http://www.CodeHighlighter.com/

    -->1 INSERT INTO [dbo].[CountryCapital] ([ID], [Country], [City]) VALUES (1, 'SWITZERLAND', 'BERN')
    2 INSERT INTO [dbo].[CountryCapital] ([ID], [Country], [City]) VALUES (2, 'GERMANY', 'BERLIN')
    3 INSERT INTO [dbo].[CountryCapital] ([ID], [Country], [City]) VALUES (3, 'AUSTRIA', 'VIENNA')
    4 INSERT INTO [dbo].[CountryCapital] ([ID], [Country], [City]) VALUES (4, 'TURKIYE', 'ANKARA')




    Die Verwendung von UNION Statement liefert aus den beiden Tabellen jeder Stadt nur einmal im als Resultat zurück. In diesem Resultat sind die Datensätze auch nach dem Ersten und dann nach dem zweiten Feld sortiert, welches nach einem ORDER BY Country, City entspricht. Für eine andere Sortierung muss der ORDER BY-Statement explizit angegeben werden.





    Code highlighting produced by Actipro CodeHighlighter (freeware)
    http://www.CodeHighlighter.com/

    -->1 SELECT Country, City
    2 FROM [dbo].[CountryCity]
    3 UNION
    4 SELECT Country, City
    5 FROM [dbo].[CountryCapital]


    Als Resultat wird folgendes ausgegeben:



    UNION



    Mit UNION ALL werden alle Datensätze der beiden Tabellen als Resultat zurückgeliefert. Die Datensätze sind in diesem Resultat nicht sortiert.





    Code highlighting produced by Actipro CodeHighlighter (freeware)
    http://www.CodeHighlighter.com/

    -->1 SELECT Country, City
    2 FROM [dbo].[CountryCity]
    3 UNION ALL
    4 SELECT Country, City
    5 FROM [dbo].[CountryCapital]


    Als Resultat wird folgendes ausgegeben:



    UNION_ALL 



    Der gesamte Beispiel Code ist wie folgt aufgelistet:





    Code highlighting produced by Actipro CodeHighlighter (freeware)
    http://www.CodeHighlighter.com/

    --> 1 BEGIN TRANSACTION
    2
    3 IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[CountryCity]') AND type in (N'U'))
    4 DROP TABLE [dbo].[CountryCity]
    5 GO
    6
    7 IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[CountryCapital]') AND type in (N'U'))
    8 DROP TABLE [dbo].[CountryCapital]
    9 GO
    10
    11 CREATE TABLE [dbo].[CountryCity]([ID] [int] NOT NULL,
    12 [Country] [nvarchar] (50) NOT NULL,
    13 [City] [nvarchar] (50) NOT NULL)
    14
    15 CREATE TABLE [dbo].[CountryCapital]([ID] [int] NOT NULL,
    16 [Country] [nvarchar] (50) NOT NULL,
    17 [City] [nvarchar] (50) NOT NULL)
    18
    19
    20 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (1, 'SWITZERLAND', 'ZURICH')
    21 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (2, 'SWITZERLAND', 'BERN')
    22 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (3, 'SWITZERLAND', 'GENEVA')
    23 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (4, 'GERMANY', 'BERLIN')
    24 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (5, 'GERMANY', 'HAMBURG')
    25 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (6, 'GERMANY', 'MUNICH')
    26 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (7, 'AUSTRIA', 'VIENNA')
    27 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (8, 'AUSTRIA', 'GRAZ')
    28 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (9, 'AUSTRIA', 'LINZ')
    29 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (10, 'TURKIYE', 'ISTANBUL')
    30 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (11, 'TURKIYE', 'ANKARA')
    31 INSERT INTO [dbo].[CountryCity] ([ID], [Country], [City]) VALUES (12, 'TURKIYE', 'IZMIR')
    32
    33 INSERT INTO [dbo].[CountryCapital] ([ID], [Country], [City]) VALUES (1, 'SWITZERLAND', 'BERN')
    34 INSERT INTO [dbo].[CountryCapital] ([ID], [Country], [City]) VALUES (2, 'GERMANY', 'BERLIN')
    35 INSERT INTO [dbo].[CountryCapital] ([ID], [Country], [City]) VALUES (3, 'AUSTRIA', 'VIENNA')
    36 INSERT INTO [dbo].[CountryCapital] ([ID], [Country], [City]) VALUES (4, 'TURKIYE', 'ANKARA')
    37
    38 SELECT Country, City
    39 FROM [dbo].[CountryCity]
    40 UNION
    41 SELECT Country, City
    42 FROM [dbo].[CountryCapital]
    43
    44
    45 SELECT Country, City
    46 FROM [dbo].[CountryCity]
    47 UNION ALL
    48 SELECT Country, City
    49 FROM [dbo].[CountryCapital]
    50
    51 ROLLBACK TRANSACTION


    Die Beispieldatei findet Ihr unter: UNION_and_UNION_ALL_Sample_0001.sql

    Silverlight Foto Album Steuerelement

    03.05.2008 18:31:00 | Mario Meir-Huber

    Ich war am Wochenende wieder mal fleißig und habe ein Control gebastelt, welches ein Fotoalbum anzeigt. Als Datenspeicher wird hierfür XML verwendet. Zwischen einzelnen Fotos kann man auch ganz einfach navigieren. Ferner kann man durch Klick auf ein Album zu einem Unteralbum navigieren.

    Das Control ist in der MS Public Licence auf Codeplex erhältlich:

    http://www.codeplex.com/photoalbum

    Ein Beispiel ist auf meinem Server vorhanden:

    http://www.meirhuber.de/picturealbum/

    Regeln | Impressum