Monday, October 17, 2011

Web Application Performance Tuning

In my actual project I have to do the performance tuning of a Microsoft Dynamics CRM System. From a technical viewpoint this is just an ASP.NET WebForms and WCF Services application. Therefore I was looking for some tools to monitor and analyse a web application. The customer don't want to spend any money on a tool, therefore it has to be free, open source or at least under $100.-. Here is a list of what I have found and what I use now.

IE Developer Toolbar
Used to analyse the HTML that is rendered in the browser. Very usefull to fix design bugs.

Fiddler2
Used to analyse what is sent and received over the wire. Analyse traffic, header information, etc.

DynaTrace Ajax Edition
Used to analyse what's going on on the client. Used to analyse CPU and memory usage, JavaScript, etc.

IntroScope
Used to analyse what happens on the server. Used to analyse CPU and memory usage, code, queries to the db, etc.

Not used yet
- HttpWatch
- NetMon
- Windows Performance Monitor
- Windows Resource Monitor
- Visual Round Trip Analyser
- Performance Toolkit for Microsoft Dynamics CRM 2011

Any further recommendations are very welcome. Write your comment!

Tuesday, October 11, 2011

jQuery Mobile 1.0 RC1 released

The future is mobile.

At the Microsoft conference Build last month, ASP.NET MVC 4 was announced and with it the jQuery Mobile Framework. Since a few days jQuery Mobile 1.0 RC1 is released. But what is jQuery Mobile?

There Website tells us:
A unified user interface system across all popular mobile device platforms, built on the rock-solid jQuery and jQuery UI foundation. Its lightweight code is built with progressive enhancement, and has a flexible, easily themeable design.

So let's see what it does and how it can be used. I build a small demo web application with ASP.NET MVC 4. Based on the AdventureWorks database and the vendor table I got a form that looks in the Windows Phone emulator like that.

Looks not too bad but not really phone like. Via NuGet I install jQuery.Mobile.MVC which is based on jQuery.Mobile. After the installation I already have a new design because of the new MasterPage that was installed with the package. The site looks like:


Much better already. But where does this changes come from? If we take a look at the new mobile MasterPage we'll find the following code: 

In this code snippet we see two new attributes (data-role and data-theme) which belong to jQuery Mobile and they are the reason for the new formatting.

If we like to format the Create New link on top of the side, so it will be a touchable button instead of the normal link, it's that simple. Just add the attribute data-role="button" and if you also like an image next to it data-icon="plus". After that small change it looks like:

Pretty easy, isn't it. There are a lot more functionality and design stuff in jQuery Mobile. Check out there website and attend my session at TechDays in Bern.

Tuesday, September 27, 2011

ASP.NET MVC 4 Developer Preview Released

At the Build conference Microsoft has announced the availability of ASP.NET MVC 4 Developer Preview. The following are the some of the new features of ASP.NET MVC 4 Developer Preview.
◦Enhancements to Default Project Templates
◦Mobile Project Template
◦Display Modes
◦jQuery Mobile, the View Switcher, and Browser Overriding
◦Recipes for Code Generation in Visual Studio
◦Task Support for Asynchronous Controllers

For more information join my talk on Oktober 21, 2011 at TechDays in Bern. Hope to see you there!

Tuesday, September 20, 2011

Windows 8, WinRT, .NET 4.5 and more

Last week at the Build conference in Anaheim CA lots of new announcements have been made. The big things were Windows 8, Metro Style Apps and WinRT. But also .NET 4.5, ASP.NET MVC 4 and other new stuff came up.

Sadly I had to stay at home and did not get all the information from the remarkable experts who were speaking at Build (and did not get the cool tablet). But after I read a lot of Blogs and talked to a lot of friends (some have been there) I will write in this post what the most important news is to me.

Windows 8 has two modes. The Desktop mode addressing the business needs using keyboard and mouse (this is where all our Win7 Apps are running in the future) and the new Metro style mode addressing the lifestyle needs with touch etc.
Therefore there are also two development stacks. The big picture is shown below.



On the right side there is the Desktop mode stack in blue with .NET 4.5, C# ?, Silverlight 5, WPF ?, HTML 5, etc. Pretty much the same as we’re having today.
On the left side in green there is the new Metro style mode stack with WinRT, C# 5, XAML, HTML 5 etc. that brings the big news.

WinRT
Also WinRT is not completely new. WinRT covers a great part of the Win32 functionality and many of the .NET 4.5 libraries are also (unmanaged) WinRT libraries. But stuff like WinForms etc. will definitely not be part of WinRT and can be found just in the Desktop App part where the full .NET 4.5 framework is located.
A thin managed layer gives the developer the C# programming API. With C++ this layer is not needed what could be an advantages for some critical scenarios. JavaScript uses the Chakra Engine to access WinRT.
Fast and fluid is what we heard a lot when someone talks about Metro style apps. There is a good chance that the WinRT APIs are mostly asynchronous. The C# 5 features will help as to handle this approach.

Portability
HTML/JavaScript Metro style apps are not typical web programming and are not cross platform. Furthermore they will be build specially for Windows 8 using the WinRT APIs.
XAML/C# Metro style apps are neither Silverlight nor WPF. They are something new using the WinRT APIs. Silverlight and WPF Apps are still present on the Desktop App side.

Business thoughts
Pretty cool all this new possibilities (Metro style apps) and all the old ones (Desktop apps) are also still working (even WinForms). Pretty cool that I can use all my existing knowlege to build the app of the future by only learning a few new things (WinRT).
As a developer employed by a software vendor working on one product I'm probably really happy. I can choose the technology I'm familiar with and addresses my needs best.
Being a .NET consultant at Trivadis it's not just fun because my boss expects me to do whatever my next customer prefers and therefore I do have to know just everything. And what about a service and maintenance team if every app comes in another technology?
Am I completely wrong by thinking the wide range of technologies ends up in superficial knowledge and in a next step in bad quality? Probably it would have been a good idea to make the world a little bit easier!

Wednesday, May 04, 2011

TechDays 11, ASP.NET MVC

TechDays 11 in Basel are over and we all had a great time with lot of interesting informations.

On the TechDays Website you will find soon the recordings and the slides.

If anybody is interested in the demo application of my Speech "Mit ASP.NET MVC zur praxistauglichen Webseite" please let me know and I will send it to you.

If you missed my speech your next chance to get more information about ASP.NET MVC and Razor is at the See#Party in Konstanz.

Thursday, April 21, 2011

Razor Inside Templates

In the dot.NET Magazin 4.2011 I wrote an article about Razor, the new view engine that comes with ASP.NET MVC 3. Therefore, it is probably obvious that I worked a lot with Razor. Despite all my work with this amazing new view engine I really love, I just discovered this week another interesting feature which I call the "Razor Inside Templates".

So what is it all about? Let's take a look at an easy example:



Even so this is a very simple example, there are some magic points to look at.

First we define a Func with the parameter type string and get back a return value with the type HelperResult. Instead of the string parameter we could use any type. Even dynamic is an option so we can pass in an anonymous type. This is shown in the next example.



The second magic point is the item object. With the @item it is possible to access the parameter data passed in. Now the basics are clear and we love the inside templates. But is this all or where does this lead us to?

Think of the possibility to write an extension method doing a loop. Instead of just passing in the data, the extension method can accept a template as a parameter. So we could build a WebForms Repeater control. Interesting thought, right?

Let's take a look at the example.


This is the extension method doing the loop by using the template.


And that's how I used the above extension method to list all vendor names from the AdventureWorks database by using a template.

There are many more situation where we can use the inside template feature to build code in a simple and nice way and where we can reuse the functionality because of the templating option.

More about it and how it works under the hood, you can read in this blog by Andrew Nurse.

Monday, March 28, 2011

Localized Validation with DataAnnotations in Silverlight

Like the title explains, I like to validate input in my Silverlight application. I want to do it with DataAnnotations and I also want my ErrorMessages to be in the language of the user. Sounds pretty easy, not?

My solution has the following projects
- Data project with my Entity Framework Model
- Web project hosting my Silverlight application and my WCF RIA Services
- Silverlight project, that’s my application

The idee of DataAnnotations is to define the validation in one place and use it in all clients. WCF RIA Services as well as ASP.NET MVC generate client code based on the server site DataAnnotations and that’s pretty cool.

Therefore I build a partial class for my entity ‘Foo’ and set the attribute [MetadataType(typeof(FooMetadata))] on it and build the ‘FooMetadata’ class in which I set the DataAnnotations attributs. To be precise I define the Required attribute on my property ‘Name’. All that in a central place, the Data project.

Then I run the application. Everything works fine. Great!

Now I need the localization. I'm adding a resx File with the error messages for my validation. On the Required attribute I add the resources like this [Required(ErrorMessageResourceName = "Required", ErrorMessageResourceType = typeof(ValidationResources))]. So far so good. Now I build the project and I get an error in the client side class generated thru the WCF RIA Services instead of the DataAnnotations attribute. Type ValidationResources is not known in the client project does it say. Hmm, that's probably right.

First idea is to add a common project to my solution, add the resx to this project and reference it from the Silverlight and the Data project. Bad idea because the Silverlight project can only refer Silverlight projects and the Data project is not happy with a Silverlight class library. So I could go the long way and add a 'normal' class library with the resx File and a Silverlight class library with the resx files linked in and so on.

I do it the simple way and link the resx files from the Data project direct to my Silverlight project by clicking Add->Existing Item->Add as Link. Now I got the type with the same namespace in both projects. To make it look nice in Visual Studio I can edit the Silverlight project file and add the dependency beetween the resx and the generated code file in notepad.
WCF RIA Services are generating the right classes with all the attributes and the solution is building. Are we done yet?

When I run the application I discover one last problem. In my generated resx access code file I find the following line:
… global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Namespace.ValidationResources", typeof(ValidationResources).Assembly);…

Because the namespace is different in the two projects, the resx (XML) file can’t be found at runtime. If I change it to the Silverlight project namespace, everything works fine. But if I would run the custom tool again, my changes are gone. This is not a good solution.

So I move the resx file to the Silverlight application. Everything is generated the right way here. Now I link in the generated code file in the Data project to make the type available for the DataAnnotations attributes. That’s it.

It's also not the perfect solution because if I do have a secound GUI like an ASP.NET MVC application I do need the resx file also in this project. So, if there is a better solution out there please let me know!

Friday, January 21, 2011

ASP.NET and asynchronous communication

Today I had to add a delete function to an old ASP.NET WebForms website. It was missing because there are a lot of relational data. So the steps to delete a record are:
- Click delete button
- Proof of existing relational data
- Show the result to the customer (and ask what to do)
- Delete all or cancel the delete action

Because I'm used to work with ASP.NET MVC, I thought on jQuery to solve the problem. Async calls to an Action on a Controller class and showing the result in a modal popup are easy tasks to do in ASP.NET MVC. This because of the MVC architecture, specially the Routing Engine used in MVC.
But in this case, I had to deal with ASP.NET WebForms and no routing to a Controller class. So how to solve the problem? I saw four different ways to do it:
1) Build a WCF Service and call it with jQuery
2) Create a ashx handler and call it with jQuery
3) Set the [WebMethod] Attribute to a method in the aspx page and call it with jQuery
4) Use the ScriptManager, the [WebMethod] and [ScriptMethod] Attribute


The first option (1), building a WCF Service is to much work for this small task.


The secound option (2) is quite good. The only thing I don't like is, I have to deal with two files what makes maintainance harder. Let's take a look at this solution anyway.
The jQuery code to call the handler looks like:

$(document).ready(function () {
$("#deleteButton").click(function () {
$.ajax({
type: "POST",
url: "Handler1.ashx",
data: "{'siteId':'" + id + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
// What you like to do on success
},
fail: function (msg) {
// What you like to do on error
}
});
});
});

The Handler (ashx-File) can be added easily with Visual Studio. Just select the Generic Handler template. The code looks like:

public class Handler1 : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
// Check for relational data and generate the message
var message = "Generated message for the user";

context.Response.ContentType = "text/plain";
context.Response.Write(message);
}
...
}


The third option (3) is in this case my favorite. Simple and easy. The jQuery call is the same, just the URL changes to something like
...
url: "SiteName.aspx/IsDeletable",
...
where the parameter after the slash is the name of the method.
In the ASPX-File we have to add a static method and decorate it with the [WebMethod] attribute. That's it! The code looks like:

[WebMethod]
public static string IsDeletable(Guid siteId)
{
// Check for relational data and generate the message
var message = "Generated message for the user";
return message;
}

IMPORTANT: The method has to be static.


The last option is ASP.NET WebForms specific and uses the ScriptManager. In my opinion do we have a better solution with the jQuery version. Anyway, here is what you need:

Add a ScriptManager as follow:
... ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true" ...

Add JavaScript code to make the call:
...
PageMethods.IsDeletable(id);
...
Notice that this is just the call. Get and handle the return value has to be added as well.

And on the method in our aspx-File we do need an additional attribute:
[System.Web.Script.Services.ScriptMethod()]


Now it's up to you to choose your right solution.

Friday, January 14, 2011

Everything just random?

Today I had to fix some code of a colleague. To test the class I've fixed, there was a mock class generating random testdata. But this testdata were always the same. So I looked also at this problem and found the following code:

for (int i = foo; i < bar; i++)
{
return new Random().Next();
}

Looks good at first glance, but this will always return the same number (at least in the same second). This is because the Random class uses in the default constructor a time-dependent default seed value.

An easy way to fix the problem would be to use the overloaded constructor and provide a unique seed value. For example just the int value i used for the for loop. This could look like:

for (int i = foo; i < bar; i++)
{
return new Random(i).Next();
}

Another way to get random numbers would be in using the Next method in a correct way. This meens on the same instance of the Random class. In this case the initialization of the Random class has to be outside the loop. The code would look like this:

var r = new Random();
for (int i = foo; i < bar; i++)
{
return new r.Next();
}

This way would definitely be better, then we need just one instance of the Random class.

Further information on the Random class can be found here http://msdn.microsoft.com/en-us/library/system.random.aspx.

Tuesday, January 04, 2011

Relaunch

Welcome back!
After a pretty long break in blogging I'm starting over again. Trivadis gave me a good reason for it ;-) Hopefully there are coming up a lot of interesting themes in 2011.

I'm sure ASP.NET MVC will be big also this year with the release of version 3. I'm doing definitely some interesting post about it. But my first activity is a speech for MSUGS on February 17, 2011. For more infos visit MSUGS. And I will do a session at TechDays 2011 in May as well.

Further there will be the first public beta release of Silverlight 5 in spring with many new cool features like:

  • Richer Media Support
  • 3D Support
  • P/Invoke
  • Elevated rights in the browser
  • Vector printing
  • Multiple windows (out-of-Browser only)
  • Improved DataBinding (almost like in WPF)
  • Custom MarkupExtensions
  • Debugging DataBinding
  • UI Testing

So stay tuned!

Friday, April 10, 2009

ASP.NET MVC

Nachdem ich mich nun seit rund einem Jahr mit dem ASP.NET MVC Framework beschäftige, durfte ich an den TechDays 2009 in Bern einen entsprechenden Vortrag halten. Die Slides und Demos werden in Kürze unter TechDays verfügbar sein.

Tuesday, March 11, 2008

Virtual, new and override - the differences

Auf die Frage was ist der Unterschied zwischen new und override, im konkreten Fall für ein Property verwendet, bekommt man stehts die korrekte Antwort. New versteckt das Property in der Basisklasse, override überschreibt dieses. Gut, aber was heisst das genau? Nun werden die sinnvollen Antworten doch eher rare.

Folgendes Beispiel zeigt die Funktionsweisen auf. Parent ist die Basisklasse, die zwei Properties Foo und Bar anbietet. Child ist eine Klasse die von Parent ableitet und die beiden Properties einmal mit new und einmal mit override überschreibt. In der Klasse MyClass werden zwei Instanzen von Child erzeugt, wobei im ersten Fall die Deklaration auf die Basisklasse Parent lautet. Die beiden Properties der beiden Instancen werden abgefragt und ausgedruckt.

public class MyClass
{
public static void Main()
{
Parent p = new Child();
Child c = new Child();
Console.WriteLine(p.Foo);
Console.WriteLine(p.Bar);
Console.WriteLine(c.Foo);
Console.WriteLine(c.Bar);
Console.ReadLine();
}
}
public class Parent
{
public string Foo {get{return "ParentFoo";}}
public virtual string Bar {get{return "ParentBar";}}
}
public class Child : Parent
{
public new string Foo {get{return "ChildFoo";}}
public override string Bar {get{return "ChildBar";}}
}

Das aufschlussreiche Ergebniss sieht so aus:
ParentFoo
ChildBar
ChildFoo
ChildBar

Da zwei Instancen von Child erzeugt wurden ist der Ausdruck ParentFoo doch für den einen oder anderen erstaunlich. Wie kommt das? Die Antwort liegt im Early- und Late Binding.

Im Fall von Foo wurde das Property auf der Parent Klasse nicht mit virtual deklariert. Somit wird das Early Binding verwendet. Das heisst, der Compiler legt zur Kompilierzeit fest welches Property aufgerufen wird. Da im ersten Fall die Variable als Parent deklariert ist, wird in jedem Fall (egal was für eine Instanz effektiv vorhanden ist) das Property Foo der Klasse Parent aufgerufen und im zweiten Fall das Property der Klasse Child.

Im Fall von Bar wurde das Property auf der Basisklasse mit virtual deklariert und somit das Early Binding verhindert. Das heisst, das zur Laufzeit die Instance analysiert wird und entsprechend das Property der effektiv vorhandenen Klasse (in unserem Fall Child) aufgerufen wird.

Und zum Schluss noch einen Blick auf den IL Code:

.method public hidebysig static void Main() cil managed
{
.entrypoint
.maxstack 1
.locals init (
[0] class Parent parent,
[1] class Child child)
L_0000: newobj instance void Child::.ctor()
L_0005: stloc.0
L_0006: newobj instance void Child::.ctor()
L_000b: stloc.1
L_000c: ldloc.0
L_000d: callvirt instance string Parent::get_Foo()
L_0012: call void [mscorlib]System.Console::WriteLine(string)
L_0017: ldloc.0
L_0018: callvirt instance string Parent::get_Bar()
L_001d: call void [mscorlib]System.Console::WriteLine(string)
L_0022: ldloc.1
L_0023: callvirt instance string Child::get_Foo()
L_0028: call void [mscorlib]System.Console::WriteLine(string)
L_002d: ldloc.1
L_002e: callvirt instance string Parent::get_Bar()
L_0033: call void [mscorlib]System.Console::WriteLine(string)
L_0038: call string [mscorlib]System.Console::ReadLine()
L_003d: pop
L_003e: ret
}

Würde man nicht erwarten, dass beim Early Binding ein call und nicht ein callvirt aufgerufen wird? Eigentlich schon. Das callvirt wird generiert, damit die Klasse auf null geprüft werden kann. Der JIT Compiler wird aber nach der null Prüfung diesen Aufruf effektiv in einen non-virtual Aufruf umsetzen.

Wednesday, January 02, 2008

Mehrere Tabellen auf eine Entität mappen

Meistens sind Daten in einer Datenbank normalisiert abgelegt. In der Applikation möchte man aber oft mit den nicht normalisierten Daten arbeiten. Ist das ADO.NET Entity Framework die Lösung?

Jein lautet die Antwort. Und um es vorne weg zu nehmen, ein Mapping von mehreren Tabellen auf eine Entität ist möglich, aber nur wenn diese eine 1:1 Beziehung haben. Das heisst, in den meisten Fällen wird man besser fahren, wenn auf der Datenbank eine geeignete View erstellt, diese auf die Entität gemapped und das Update, Insert und Delete über Stored Procedures gelöst wird.

Nun aber zur Lösung. Zuerst wird ein Model mit dem Assistenten erstellt, das alle gewünschten Tabellen enthält.

Die Anpassungen am Conceptual Model (CSDL) sind einfach. Auf der Entität werden die gewünschten Attribute aus den weiteren Tabellen hinzugefügt. So wurde etwa hier die Entität Cars um das Attribut Value erweitert.

<?xml:namespace prefix = edmx /><edmx:conceptualmodels>
<schema xmlns="http://schemas.microsoft.com/ado/2006/04/edm" alias="Self" namespace="Model">
<entitycontainer name="Entities">
<entityset name="Cars" entitytype="Model2.Cars">
</entitycontainer>
<entitytype name="Cars">
<key>
<propertyref name="ID_Cars">
</key>
<property name="ID_Cars" nullable="false" type="Guid"></property>
<property name="Brand" type="String" maxlength="50"></property>
<property name="Model" type="String" maxlength="50"></property>
<property name="Value" type="String" maxlength="50"></property>
</entitytype>
</schema>
</edmx:conceptualmodels>

Anpassungen am Storage Model (SSDL) sind keine notwendig, da sich an der Datenbank, welche durch dieses Model repräsentiert wird, nichts ändert.

Durch Anpassung des Mappings werden die neu definierten Attribute auf der Entität nun auf die im Storage Model vorhandenen gemapped. Dies wird realisiert durch Hinzufügen eines zusätzlichen Mapping Fragment.

<edmx:mappings>
<mapping xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS" space="C-S">
<entitycontainermapping cdmentitycontainer="Entities" storageentitycontainer="dbo">
<entitysetmapping name="Cars">
<entitytypemapping typename="IsTypeOf(Model.Cars)">
<mappingfragment storeentityset="Cars">
<scalarproperty name="ID_Cars" columnname="ID_Cars">
<scalarproperty name="Brand" columnname="Brand">
<scalarproperty name="Model" columnname="Model">
</mappingfragment>
<mappingfragment storeentityset="Extensions">
<scalarproperty name="ID_Cars" columnname="ID_Extensions">
<scalarproperty name="Value" columnname="Value">
</mappingfragment>

</entitytypemapping>
</entitysetmapping>
</entitycontainermapping>
</mapping>
</edmx:mappings>

Nicht mehr benötigter Code wie EntitySets und AssociationSets sind im CSDL und dem Mapping zu löschen.

Wednesday, December 19, 2007

Vom Namen zur Instanz mit DynamicMethod

Ein Kunde legt beim Logging unterschiedliche LogMessages (unterschiedliche Klassen) in einer Datenbank ab. Dabei werden der Typ der Message (der LogMessage Klassenname), die Message selber sowie weitere Felder in der Tabelle gespeichert.
Nun sollten diese Einträge gelesen und die ursprünglichen Objekte wieder hergestellt werden.

Für die erste Lösung wurde der offensichtliche Weg mit Reflection gewählt:

string s = "Namespace.Name.FromDB";
Assembly a = Assembly.GetAssembly(typeof(ThisClass));
Type t = a.GetType(s);
BaseType b = (BaseType)Activator.CreateInstance(t);

Da dies nicht sehr performant ist, wurde der Code wie folgt verbessert:

string s = "Namespace.Name.FromDB";
Assembly a = Assembly.GetAssembly(typeof(ThisClass));
Type t = a.GetType(s);
ConstructorInfo i = t.GetConstructor(Type.EmptyTypes);
BaseType b = (BaseType)i.Invoke(null);

Wobei der Klassenname und die zugehörige ConstructorInfo in einem statischen Dictionaire abgelegt werden, damit diese nicht bei jedem Aufruf neu evaluiert werden müssen. So haben wir vom zweiten bis x-ten Aufruf den gewünschten Performancegewinn. Der Code dazu sieht folgendermassen aus.

ConstructorInfo c = null;
if (_cinfo.TryGetValue(s, out c))
{
c = t.GetConstructor(Type.EmptyTypes);
lock(_cinfo)
{
if (_cinfo.ContainsKey(s))
{
_cinfo.Add(s, c);
}
}
}

Noch eleganter und viel performanter geht's mit Dynamic Methods. Der von der dynamischen Methode zurückgegebene Delegate wird wie zuvor die ConstructorInfo in einem Dictionaire abgelegt und für die Folgeaufrufe wieder verwendet:

public delegate BaseType CtorDelegate();

DynamicMethod dm = new DynamicMethod
("MyCtor", typeof(BaseType), Type.EmptyTypes, typeof(BaseType).Module);
ILGenerator ilgen = dm.GetILGenerator();
ilgen.Emit(OpCodes.Newobj, t.GetConstructor(Type.EmptyTypes));
ilgen.Emit(OpCodes.Ret);
CtorDelegate d = (CtorDelegate)dm.CreateDelegate(typeof(CtorDelegate));

Der Aufruf ist dann genau so kurz (d wird zuvor aus dem Dictionaire gelesen) und unheimlich schnell:

t message = (t)d();

Nun muss nur noch alles in einer Factory Klasse schön verpackt werden und fertig. Mehr zu diesem Thema inklusive Performance Messungen findet man wie immer bei Google ;-)

Monday, November 05, 2007

Sprachfeatures C# 3.0 und wie sie die Welt verändern

Mit dem .NET Framework 3.5 kommen erneut etliche Features zur Sprache C# 3.0 hinzu, die dem Entwickler das Leben bedeutend erleichtern (ausser man ist auf der Wartungsseite).
Automatic Properties, Extension Methods, Lambda Expressions, Anonymous Types, usw. bieten dem Entwickler vollkommen neue Möglichkeiten, was zu sehr schickem Code führen kann. Bei exzessivem Anwenden nur des Features oder der Eleganz wegen kann das aber zu schwer wartbarem und unübersichtlichen Code- und Sprachauswüchsen führen.

Trotzdem, ganz hübsche ist folgendes (auch wenn nicht sehr sinnvoll ;-):
7.TimesPrint("MeinText");

Wesentlich eleganter als:
for (int i = 0; i < 7; i++)
{
Console.WriteLine("MeinText");
}

Doch damit es funktioniert braucht's noch eine Extension Method:
Public static void TimesPrint(this int no, string s)
{
for (int i = 0; i < no; i++)
{
Console.WriteLine(s);
}
}

Etwas allgemeiner formuliert könnte der Aufruf so aussehen und so auch wirklich Sinn machen (die Extension Method muss natürlich entsprechend angepasst werden):
7.Times(i => Console.WriteLine("MeinText"));


Ob die Wartbarkeit durch die schwerer erkennbare Funktionalität komplexer oder durch die elegante Syntax doch eher erleichtert wird, wird spätestens die Praxis zeigen.

So oder so, die neuen Features machen viel Spass!

PS: Eine gute Übersicht zu den neuen Features gibt's hier.

Thursday, October 25, 2007

Output Parameter in dynamischem T-SQL

In einer Stored Procedure werden in einem ersten Schritt zwei Variablen gesetzt, die für die weitere Verarbeitung benötigt werden. Dies könnte so aussehen:

SELECT @var1 = Var1, @var2 = Var2
FROM MyTable
WHERE ID = @ID

Nun muss das Statement aber dynamisch zusammengestellt werden und der Select-String danach ausgeführt werden. Dies könnte so aussehen:

SET @query = '
SELECT @var1 = Var1, @var2 = Var2
FROM MyTable
WHERE ID = ' + CAST(@ID as CHAR(15))
EXEC (@query)

In meinem Fall wird das Statement auf einem Hostsystem ausgeführt und der Aufruf muss über Openquery gemacht werden. Dies könnte so aussehen:

SET @query = '
SELECT @var1 = Var1, @var2 = Var2
FROM OPENQUERY(MySystem, ''SELECT Var1, Var2 FROM MyTable WHERE ID = '
+ dbo.MyTypeConverter(@id) + ''')'
EXEC (@query)

Ganz klar, dass die beiden Variablen so nicht mehr abgefüllt werden, sondern zu einem Fehler führen. Wie können diese gesetzt werden?
Gemäss einer ersten Idee wurde eine Variable vom Typ TABLE verwendet und das Openquery-Resultat mit INSERT INTO angefügt. Danach das erste Select-Statement verwendet um die Variablen zu setzten. Funktioniert! Ist aber nicht sehr elegant.
Hübscher ist's so:

SET @params = ' @var1 int OUTPUT, @var2 nvarchar(max) OUTPUT'
SET @query = '
SELECT @var1Out = Var1, @var2Out = Var2
FROM OPENQUERY(MySystem, SELECT Var1, Var2 FROM MyTable '
+ dbo.MyTypeConverter(@id) + ''')'
EXEC sp_executesql @query, @params, @var1Out = @var1 OUTPUT, @var2Out = @var2 OUTPUT

Dieser Ansatz mit der System Procedure sp_executesql bietet zudem noch weitere Vorteile die in der SQL Server Hilfe nachgelesen werden können.

Friday, October 05, 2007

Dynamic Method Performance

In einem interessanten Artikel im MSDN Magazine wird auf unterschiedliche Performance Probleme, im Speziellen im Zusammenhang mit Reflection, eingegangen. Mich interessierte vor allem die gelobte Performance der dynamischen Methoden, die seit der .NET Framework Version 2.0 zur Verfügung stehen. Eine einfache Testanwendung hat gezeigt, dass der Artikel recht behält.
In der Testanwendung wird einem Objekt ein String eine Million mal zugewiesen. Dies zuerst direkt verdrahtet, danach mit dynamischer Methode und zuletzt via Reflection. Das Ergebnis ist eindeutig. Die direkt verdrahtete Methode ist natürlich die Schnellste, die dynamische Methode braucht dafür doppelt so lange (was ich immer noch sehr gut finde) und mittels Reflection dauert es 100mal länger. What a gain!
Übrigens, die Assembly habe ich mit Lutz's Reflector untersucht, um sicher zu stellen, dass die Schlaufe auch wirklich bei allen drei Varianten ausgeführt wird.

Und hier noch der Code:

public class Program
{
private delegate void DemoDelegate(Foo arg);

static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();

Foo f = new Foo();
stopwatch.Start();
for (int i = 0; i < 1000000; i++)
{
f.Text = "Hello World!";
}
stopwatch.Stop();
Console.WriteLine("Direct: {0}", stopwatch.Elapsed);

stopwatch.Reset();

DemoDelegate del = createMethod();
stopwatch.Start();
for (int i = 0; i < 1000000; i++)
{
del(f);
}
stopwatch.Stop();

Console.WriteLine("Dynamic method: {0}", stopwatch.Elapsed);

stopwatch.Reset();

PropertyInfo property = f.GetType().GetProperty("Text");
stopwatch.Start();
for (int i = 0; i < 1000000; i++)
{
property.SetValue(f, "Hello World!", null);
}
stopwatch.Stop();
Console.WriteLine("Reflection: {0}", stopwatch.Elapsed);


Console.ReadKey();
}

private static DemoDelegate createMethod()
{
Type[] parameterTypes = new Type[] { typeof(Foo) };
DynamicMethod method = new DynamicMethod("Demo", null, parameterTypes, typeof(Program));

ILGenerator iLGenerator = method.GetILGenerator();
iLGenerator.Emit(OpCodes.Ldarg_0);
iLGenerator.Emit(OpCodes.Ldstr, "Hello World!");
MethodInfo setMethod = typeof(Foo).GetProperty("Text").GetSetMethod();
iLGenerator.EmitCall(OpCodes.Call, setMethod, null);
iLGenerator.Emit(OpCodes.Ret);

return (DemoDelegate)method.CreateDelegate(typeof(DemoDelegate));
}
}

public class Foo
{
private string _text;

public string Text
{
get { return _text; }
set { _text = value; }
}
}

Friday, September 14, 2007

Remote Debbuging

Wenn man eine Applikation remote debuggen soll, wird man feststellen, dass verschiedene Punkte beachtet werden müssen, damit das Ziel erreicht wird. Einige hoffentlich nützliche Hinweise möchte ich hiermit weitergeben:

1. Remotedebugging heisst, mit dem lokalen Visual Studio eine laufende Applikation auf einer anderen Maschine, typischerweise einem Server, zu debuggen.
2. Der Applikationscode (dll und pdb Files) muss auf beiden Systemen identisch sein.
3. Auf der Remotemaschine muss der Remote Debugger, im Speziellen das File msvsmon.exe vorhanden sein. Auf der lokalen Maschine muss Visual Studio vorhanden sein.
4. Der lokale Account (unter dem Visual Studio läuft) muss auf dem Remotesystem Administratorrechte haben, damit sich Visual Studio attachen kann.
5. Auf dem Remotesystem muss der Remotedebugger (msvsmon.exe) unter dem lokalen Account (unter demselben wie Visual Studio läuft), gestartet werden (im Contextmenü Run as ... ausführen).
6. In Visual Studio muss unter Tools, Options, Debugging, General die Option ‚Enable just my Code’ inaktiv sein, damit die Symbols geladen werden und Breakepoints gesetzt werden können.
7. In Visual Studio kann nun unter Debug, Attach to Process der Remoteprozess angebunden werden. Dazu Transport: Default und Qualifier: SERVERNAME wählen. Nun den gewünschten Prozess, z. Bsp. W3wp.exe auswählen. Ist der gewünschte Prozess nicht aufgelistet, muss sichergestellt werden, dass die Applikation wirklich läuft. Dazu z. Bsp. Die Webseite aufrufen.
8. Nun wie gewohnt debuggen.

Viel Spass.

http und Textfile

Für einen Kunden sollte ich von einer Webseite (http://.../mytext.php) ein File downloaden und den Text auf einem Server Share speichern. Und so einfach ist das mit .NET 2.0.

// Get stream from any webserver over HTTP response object
WebRequest request = (WebRequest)WebRequest.Create(new Uri("http://.../mytext.php"));
WebResponse response = request.GetResponse();
// create reader to read the stream and save it in a string
StreamReader reader = new StreamReader(response.GetResponseStream());
// write string to a file
File.WriteAllText(@"c:/test.txt", reader.ReadToEnd());
// close objects
reader.Close();
response.Close();

Wednesday, February 14, 2007

Microsoft Expression - Tools for Designer or Developer?

Vier neue Produkte aus dem Hause Microsoft warten auf uns Entwickler... oder doch nicht?

* Microsoft Expression Media (endgültige Version erscheint voraussichtlich Mitte 2007)
Expression Media ist ein Produkt für das Digital Asset Management. Basierend auf der Software iView MediaPro, die im Juni 2006 von Microsoft übernommen wurde, dient es der Katalogisierung und Verarbeitung von Mediendateien wie Grafiken und Videos.

Ich denke nicht, dass dieses Produkt für Entwickler von Interesse ist.


* Microsoft Expression Design (Beta 1 verfügbar, endgültige Version erscheint voraussichtlich Mitte 2007)
Expression Design ist das Bildbearbeitungsprogramm, also der PhotoShop von Microsoft. Das Produkt deckt höchste Anforderungen ab, könnte aber auch einige Entwickler überfordern. Vielleich hält man sich da doch besser ans Paint.NET 3.0 mit dem auch ein Entwickler das gewünschte Resultat erreicht und zudem erst noch der Sourcecode vorliegt (siehe letzte Posts).

Ich denke nicht, dass dieses Produkt für Entwickler von Interesse ist.


* Microsoft Expression Web (bereits verfügbar)
Das aus Microsoft FrontPage hervorgegangene Expression Web ist eine Web-Entwicklungsumgebung die leider nicht alles bietet was man sich wünscht. Ich war total entäuscht von diesem Produkt. Zum Beispiel werden keine Themes und Skins von ASP.NET 2.0 unterstützt aber auch Basics wie ein tabellenloses Layout (mit DIV Tags und CSS) wird nicht unterstützt. Das heisst, der Designer kann's nicht anzeigen und es gibt auch keine Tools, Intellisense, ... um damit zu arbeiten.

Ich denke nicht, dass dieses Produkt für Entwickler von Interesse ist.


* Microsoft Expression Blend (Beta 2 verfügbar, endgültige Version erscheint voraussichtlich Mitte 2007)
Expression Blend ist ein Designwerkzeug für das Erstellen von interaktiven Benutzeroberflächen. Es fungiert als WYSIWYG-Editor für XAML, eine in XML formulierte Sprache zur Beschreibung und Erstellung von Oberflächen der Windows Presentation Foundation (WPF und WPF/E). Vektorgrafiken, Rastergrafiken, 3D-Objekte aus bekannten 3D-Programmen, Videos, Sound und Text lassen sich miteinander vereinen und mit Hilfe einer Zeitleiste animieren.

Ich denke, dass dieses Produkt bis zu einem bestimmten Punkt auch für Entwickler von Interesse ist. Um alle Möglichkeiten auszuschöpfen, sollte es allerdings in die Hände eines Grafikers gelegt werden.