Archiv der Kategorie: .NET

Slippery When Wet #6: XPath and the Default Namespace

I proudly present to you the sixth in a infinite number of posts of “Slippery When Wet.” In these posts I show you a little bastard I stumbled on.

Recently, I tried to work on a XmlDocument with XPath in C#. To get the right expressions easily I used the XML Spy from Altova. As soon as I got the right XPath expressions I started Visual Studio to work in my .NET Application. But here, the only expression that worked was „/*“. According to the .NET Documentation the expressions should work, but they didn’t.

So I tried another XML file, one from the examples in the .NET Documentation of XPath. And with this file the (corresponding) expressions worked as expected. So I searched the difference of the two XML files. After a short time I found the relevant difference: The file that worked had no namespace defined, whereas the non-working file had two namespaces. One namespace with a prefix (xmlns:prefix=“URI“) and a default namespaces (xmlns=“URI“).

As I got the reason for my problem I had to look for a solution. A little bit of googling brought me the solution. I had to add the default namespace to the NamespaceManager with a prefix and then use the XPath expressions with the defined prefix.

In .NET 3.5 Microsoft introduced the XDocument class as a alternative (or a replacement) for XmlDocument. The C# code differs a little bit depending on the used class. I found a description when using the XmlDocument class and two when using the XDocument class.

With the added prefix for the default namespace my XPath expressions worked as expected.

Visual T# (TSharp) – Allererster Schritt

Pretty Objects hat Visual T# in der Version 3.0 veröffentlicht. Zeit, dieses Tool einmal näher anzuschauen.

Die Installation erfolgt über ein Setup und muss hier wohl nicht weiter beschrieben werden.

Ich starte das Ganze mit einem kleinen Vergleich zwischen dem Testing Framework von Microsoft und Visual T# an einem einfachen Beispiel. Dieses Beispiel hatte ich vor einiger Zeit erstellt, um NUnit vorzustellen.

Die zu testende Bibliothek

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
namespace Calculator
{
    public class Calc
    {
        public byte Add(byte b1, byte b2)
        {
            int res = b1 + b2;
            if (res > Byte.MaxValue)
            {
                throw new OverflowException();
            }

            return (byte)res;
        }
    }
}

Die Funktion beinhaltet bereits die Überlauf-Absicherung für den zweiten Test, ansonsten nicht viel spannendes an diesem Code…

Erster Test mit Microsoft Test Framework

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
namespace CalculatorMSTest
{
    [TestClass]
    public class CalcTest
    {
        [TestMethod]
        public void AddTest()
        {
            Calc calc = new Calc();

            byte sum = calc.Add(12, 26);

            Assert.AreEqual(38, sum);
        }
    }
}

Auch hier gibt es nicht viel spannendes: Initialisierung (Zeile 9), Ausführung (Zeile 11) und Validierung (Zeile 13) wie wahrscheinlich schon tausend mal gesehen.

Der erste Test mit T#


GeSHi Error: GeSHi could not find the language tsharp (using path /home/rolandba/public_html/blog/wp-content/plugins/codecolorer/lib/geshi/) (code 2)

Auf den ersten Blick könnte man meinen, es sei auch normaler C#-Code, aber auf den zweiten Blick fallen dann die Unterschiede auf:

  1. testclass anstelle von class (Zeile 4)
    Mit dem Keyword testclass wird angegeben, dass es sich um eine Klasse für Tests handelt.
  2. test als Bezeichner für Testmethode (Zeile 6)
    Das Keyword test bezeichnet eine Testmethode. Mit dem nachfolgenden Add(byte, byte) kann angegeben werden, welche Methode mit diesem Test überprüft werden soll. Dies ist aber optional.
  3. Deklarierung des Stimuli mit runtest (Zeile 10)
    Die Anweisung, mit welcher der Stimuli des Tests ausgelöst wird, wird mit runtest bezeichnet. Somit ist klar ersichtlich, was Initialisierung und was Ausführung der Tests ist.
  4. Überprüfung mit Keyword assert. (Zeile 12)
    Für die Überprüfung gibt es das Keyword assert und nicht ein Objekt wie in den bekannten Testing Frameworks
  5. keine Attribute
    Da T# extra für Tests entwickelt wurde sind keine zusätzlichen Attribute nötig (siehe auch Punkt 1).

Eine etwas andere Syntax aber keine spektakulären Neuerungen. Ein paar eingesparte Attribute, sonst etwa der gleiche Aufwand. Bisher also kein richtiger Grund, eine neue Syntax zu lernen.

Schauen wir und noch einen zweiten Test an:

Zweiter Test mit Microsoft Test Framework

1
2
3
4
5
6
7
        [TestMethod, ExpectedException(typeof(System.OverflowException))]
        public void BigAddTest()
        {
            Calc calc = new Calc();

            calc.Add(150, 230);
        }

Der zweite Test validiert die Überlauf-Prüfung. Die erwartete Ausnahme wird als Attribut (Zeile 1) angegeben.

Der zweite Test mit T#


GeSHi Error: GeSHi could not find the language tsharp (using path /home/rolandba/public_html/blog/wp-content/plugins/codecolorer/lib/geshi/) (code 2)

Der wichtigste Unterschied betrifft die Ausnahme. Bei T# wird das Auftreten der Ausnahme ebenfalls mit einem assert Befehl validiert. Der Test folgt somit dem bekannten Schema Initialisierung (Zeile 3), Ausführung (Zeile 5) und Validierung (Zeile 7).

In diesem Beispiel haben wir aus meiner Sicht einen Mehrwert mit T#: Das Schema wird beibehalten, während bei Tests mit dem Microsoft Test Framework die Validierung in ein Attribut an den Anfang des Tests geschoben wird.

Ausblick:
T# bietet noch weitere Vorteile, die ich in einem weiteren Artikel noch beleuchten möchte.

Rekursiv vs. Iterativ

In der dotnetpro 8/2011 hat Ralp Westphal im Artikel „Aus Baum mach Fluss“ zum Einstieg die Fakultätsberechnung in der rekursiven und in der iterativen Variante gezeigt. Seiner Meinung nach ist die iterative Variante einfacher zu verstehen, besonders für nicht-Mathematiker.
Ich fragte mich dann, welche Variante ist für den Computer einfacher zu verstehen, d.h. welche Variante ist performanter? Oder ist es egal, optimiert der Compiler schon so weit, dass beide Varianten in etwa gleich schnell sind?

Ich habe ein kleines Programm geschrieben, dass die Fakultät für verschiedene Werte mehrmals berechnet, um messbare Werte zu erhalten.
Hier die Resultate:

Factorial recursive and iterative
---------------------------------

10!
Recursive: 00:00:00.0390023
Iterative: 00:00:00.0220012

100!
Recursive: 00:00:00.2940168
Iterative: 00:00:00.1720099

1000!
Recursive: 00:00:02.5131437
Iterative: 00:00:01.0270588

10000!
Recursive: 00:00:25.0624335
Iterative: 00:00:09.4535407

Die rekursive Variante braucht also etwa 2.5 mal so lang wie die iterative. Und bei grossen Fakultäten kommt noch ein weiteres Problem hinzu: Es wird eine StackOverflowException geworfen, da jeder Rekursionsschritt einen Funktionsaufruf zur Folge hat, der einen Teil des Stacks beansprucht.

Fazit:
Der iterative Ansatz ist (mindestens in diesem Fall) auch für den Computer „einfacher zu verstehen“. Neben der besseren Performance ist aber auch die gebannte Gefahr des Stack Overflows ein wichtiger Grund, die iterative Varinate vorzuziehen.

Factorial Source Code

Slippery When Wet #5: The Process object or Optimization? don’t do it!

Slippery When WetI proudly present to you the fifth in a infinite number of posts of “Slippery When Wet.” In these posts I show you a little bastard I stumbled on.

To get the memory usage information you can use the System.Diagnostics.Process class. As I wantet to check the memory usage regularly I kept the reference to the Process object in my class. But the value never changed anymore… Then I tried to get the Process object every time i needed the current memory size – and it worked.

So I read the documentation a little more carefully and got to this part:

The process component obtains information about a group of properties all at once. After the Process component has obtained information about one member of any group, it will cache the values for the other properties in that group and not obtain new information about the other members of the group until you call the Refresh method. Therefore, a property value is not guaranteed to be any newer than the last call to the Refresh method. The group breakdowns are operating-system dependent.

So I changed my code again to not get the Process every time I wanted the current memory size but call the Refresh method.

And what did we learn from this episode?

Michael A. Jackson („The First Rule of Program Optimization: Don’t do it (…)„) and Donald Knuth („(…) premature optimization is the root of all evil (…)„) are right. Don’t do optimization, especially not if you don’t really know what you are doing…

.NET Reflectors Erben

Nachdem redgate Anfangs Februar Ankündigte, dass der .NET Reflector kostenpflichtig wird, haben sich mehrere Nachfolger empfohlen:

Als erstes kündigte das Team von #develop das Tool ILSpy an.

Danach folgte Telerik mit JustDecompile.

JetBrains, welche sich auch für … verantwortlich zeichnen, kündigten dann auch noch einen Erben an, das Tool dotPeek.

Redgate kündigte währenddessen an, dass es weiterhin eine kostenlose Version von .NET Reflector geben wird. Es ist in diesem Bereich also noch einiges in Bewegung…

Auswahl der zu benutzenden Framework-Version

Um eine .net-Applikation mit einer bestimmten Framework-Version auszuführen, kann diese im App.Conifg-File angegeben werden. Mit folgendem Beispiel wird die Anwendung mit dem Framework 1.1 ausgeführt, wenn man den Kommentar um das andere supportedRuntime-Tag setzt, wird das Framework 2.0 verwenden.

< ?xml version="1.0" encoding="utf-8">
<configuration>
   <startup>
      <supportedruntime version="v1.1.4322"/>
<!--      <supportedRuntime version="v2.0.50727"/>-->
   </startup>
</configuration>

Die Datei muss dabei dem Dateinamen der Anwendung mit angehängtem .config entsprechen, z.B. für die Anwendung „MyApp.exe“ heisst die Datei „MyApp.exe.config“.

Slippery When Wet #2: SCOPE_IDENTITY and SqlDataReader

I proudly present to you the second in a infinite number of posts of “Slippery When Wet.” In these posts I show you a little bastard I stubled on.

Imagine you have a database table with a cloumn id of the data type integer that has set the IDENTITY. You use a stored procedure to insert a new entry into this table. Inside this stored procedure you use the SCOPE_IDENTITY() function to get the identifier created for this row. With RETURN SCOPE_IDENTITY() you give the identity to the caller.

You call this stored procedure from a SqlComand with ExecuteReader() that returns you an SqlDataReader object.

From this SqlDataReader you read now the identifier with GetInt32().

Wrong !

This will give you an InvalidCastException. SCOPE_IDENTITY()’s return type is numeric, although your identifier column is an integer. SqlDataReader’s GetXY functions do not convert the data and throw the exception when the data is not already of the right type.

The first solution

You can read the value with GetDecimal() and cast the value to an int:

int identifier = (int)reader.GetDecimal(0);

The second solution

You cast the identifier inside the stored procedure und return it already as an integer:

SELECT CAST(SCOPE_IDENTITY() AS INT)

Whatever solution you choose, take care that you use always the same inside your application.

Exception after sending data async from a thread

If you have a situation like this:

void MyThreadFunc()
{
// do some work

socket.BeginSend(buffer, 0, buffer.Length, 0, new AsyncCallback(MyCallback), s);
}

void MyCallback(IAsyncResult ar)
{
Socket s = (Socket) ar.AsyncState;
s.EndSend(ar);
}

And you send a big buffer over a slow connection it can happen that calling EndSend() will throw a SocketException ‚The I/O operation has been aborted because of either a thread exit or an application request‘.

This happens because the Thread that started the sending is no more available when the sending ends. The only solution I know is to make sure the thread is still available or to use syncronous sending if possible.

Benutzen der NAnt-Properties

Der Zugriff auf die NAnt-Properties ist meiner Meinung nach etwas unglücklich gewählt, da zwei verschiedene Varianten je nach Kontext benutzt werden müssen.

Folgendes Beispiel zeigt sehr schön die beiden Varianten, wie NAnt-Properties im jeweiligen Zusammenhang angewendet werden müssen:

<delete file="${Directory}${File}.new"
if="${file::exists(Directory + '' + File + '.new')}" />

Dieser Befehl löscht die Datei, falls sie vorhanden ist. Für den Dateinamen muss die Syntax mit dem ${} benutz werden, die so genannte ‚property expansion‘.

Für die Bedingung wird dann die Methode für den Zugriff auf das Property innerhalb einer Expression benutzt. Dabei wird auf ${} verzichtet.