Previous month:
January 2006
Next month:
April 2006

March 2006

LINQ Part 4 - What's behind a query expression?

With part 1 to 3 of this series, I've shown a query expression like the following to filter and sort data.

var winners = from r in racers
   where r.Wins > 3
   orderby r.Wins descending
   select r;

What's behind a query expression consisting of from, where, orderby descending, select? A query expression with this new C# 3.0 syntax simply resolves to methods that are invoked:

IEnumerable<Racer> winners = racers.
   Where(r => r.Wins > 3).
   OrderByDescending(r => r.Wins).
   Select(r => r);

The methods Where, OrderByDescending, Select are extension methods. Extension methods are static methods that can extend other classes.
Here is some information about how to write a custom extension method.

What about r => r.Wins > 3? This is a lambda expression that is an advancement of anonymous methods. The same code as before using extension methods and lamdba expression can be written using extension methods and anonymous methods:

IEnumerable<Racer> winners = racers.Where(
   delegate(Racer r)
   {
      return r.Wins > 3;
   }).OrderByDescending<Racer, int>(
   delegate(Racer r)
   {
      return r.Wins;
   });

The lambda expression r => r.Wins > 3 resolves to a method with the parameter r, and a body where the result from r.Wins > 3 is returned. The syntax of the lambda expression looks easier compared to anonymous methods.

More information to follow. The previous parts of this series:

Christian


LINQ Part 3 - Filtering and Sorting XML

LINQ Part 1 was about filtering and sorting object lists. LINQ Part 2 had the same result with information from the database. In part 3 I'm showing how to get the same information from XML data.

The XML data I'm using is similar to the data from the database from part 2:

<Racers>
  <Racer>
    <Name>Fernando Alonso</Name>
    <Car>Renault</Car>
    <Wins>9</Wins>
  </Racer>
  <Racer>
    <Name>Giancarlo Fisichella</Name>
    <Car>Renault</Car>
    <Wins>2</Wins>
  </Racer>
  <!-- ... -->

</Racers>

The requirement now is - as it was before - to filter the racers by selecting only the racers that have more than three wins, and sorting the result by the number of wins.

Doing this the "traditional" way, it is possible to filter the racers using an XPath expression: /Racers/Racer[Wins > 3]. However, this doesn't do a sort. The resulting list can be sorted by sorting the object list. Here I've chosen to filter and sort using XML features: XSLT. The select attribute specifies the XPath filter expression, and the resulting elements are sorted according to the xsl:sort element:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="
http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <Racers>
      <xsl:apply-templates select="/Racers/Racer[Wins > 3]">
        <xsl:sort select="Wins" data-type="number" order="descending"/>
      </xsl:apply-templates>

    </Racers>
  </xsl:template>
  <xsl:template match="Racer">
    <Racer>
      <Name>
        <xsl:value-of select="Name"/>
      </Name>
      <Wins>
        <xsl:value-of select="Wins"/>
      </Wins>
    </Racer>
  </xsl:template>
</xsl:stylesheet>

Using the XslCompiledTransform (.NET 2.0) class, the XML document is transformed written to a memory stream:

XslCompiledTransform transform = new XslCompiledTransform();
   transform.Load("Racers.xslt");

MemoryStream stream = new MemoryStream();
XmlTextWriter output = new XmlTextWriter(stream, Encoding.UTF8);
transform.Transform("Racers.xml", output);

The XML data in the memory stream is loaded inside the XmlDocument class, and here all racers are iterated with a foreach:

XmlDocument resultDoc = new XmlDocument();
stream.Seek(0, SeekOrigin.Begin);
resultDoc.Load(stream);

foreach (XmlNode racer in resultDoc.SelectNodes("Racers/Racer"))
{
    Console.WriteLine("{0} {1}", racer.ChildNodes[0].InnerText,
         racer.ChildNodes[1].InnerText);
}

Now to a new version: how can the same result be achived using XLINQ?

XElement is a new class that represents an XML element but also allows loading XML data with the static Load method. Now similar to accessing data from objects and the database, with the XLINQ query expression from where orderby select, data can be filtered and sorted. racers.Elements("Racer") accesses all Racer elements. r.Elements("Wins") accesses the Wins element that is a child of a Racer element. Because the Wins element is optional, a cast to a nullable int int? is performed.

var racers = XElement.Load("Racers.xml");

var winners = 
   from r in racers.Elements("Racer")
   where (int?)r.Element("Wins") > 3
   orderby (int?)r.Element("Wins") descending
   select (string)r.Element("Name") + " " + (string)r.Element("Wins");

foreach (string name in winners)
{
    Console.WriteLine(name);
}

Comparing how to filter and sort XLINQ with XSLT, XLINQ has the great advantage that it uses the same principles as accessing object lists (LINQ) and accessing data from the database (DLINQ). There's no need to learn a complete different syntax as XSLT.

Christian


LINQ Part 2 - Filtering & Sorting Using Data from the Database

In the first part of this LINQ series I've shown how to filter and sort an object list:

var winners = from r in racers
   where r.Wins > 3
   orderby r.Wins descending
   select r;

foreach (Racer r in winners)
{
   Console.WriteLine("{0}, {1}", r.Name, r.Wins);
}

Now I'm showing the same result from racers stored inside the database. Racers should be filtered according to the number of race wins, and sorted.

The traditional way is by creating a connection using an ADO.NET connection class, defining the SELECT statement using the SqlCommand class and defining a SELECT statement including WHERE and ORDER BY. With a data reader all records that are already sorted can be read.

SqlConnection connection = new SqlConnection(@"server=localhost\yukon;database=Formula1;trusted_connection=true");
SqlCommand command = connection.CreateCommand();
command.CommandText = "SELECT Name, Wins From Racers WHERE Wins > 3 ORDER BY Wins DESC";
connection.Open();
SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection);
while (reader.Read())
{
   Console.WriteLine("{0}, {1}", 
      reader.GetString(0),
      reader.IsDBNull(1) ? 0 : reader.GetInt32(1));
}
reader.Close();

How can the same be achieved usind DLINQ?

Formula1Database db = new Formula1Database(@"server=localhost\yukon;database=Formula1;trusted_connection=true");

var winners = from r in db.Racers
      where r.Wins > 3
      orderby r.Wins descending
      select r;

foreach (Racer r in winners)
{
      Console.WriteLine("{0} {1}", r.Name, r.Wins);
}

Compare the code accessing the database with the code from the first part of the article accessing an object list. The same syntax is used accessing object lists and data from the database.

To get the data from the database, the Formula1Database class derives from the base class DataContext. With the constructor a connection string is passed to the base class. The class also contains a field that maps to the Racers table in the database returning Racer objects.

    public class Formula1Database : DataContext
    {
        public Formula1Database(string fileOrServerOrConnection)
            : base(fileOrServerOrConnection)
        {
        }

        public Table<Racer> Racers = base.GetTable<Racer>();

    }

The mapping to the Racers table in the database is defined with [Table] and [Column] attributes:

   [Table(Name="Racers")]
    public class Racer : IComparable<Racer>
    {
        //...

        [Column(Id=true)]
        private int id;

        private string name;

        [Column]
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        private string car;

        [Column]
        public string Car
        {
            get { return car; }
            set { car = value; }
        }

        private int wins;

        [Column]
        public int Wins
        {
            get { return wins; }
            set { wins = value; }
        }

        //...

Part 3 will show how filtering and sorting can be done using XML data.

Christian


LINQ Part 1 - Filtering & Sorting Object Lists

Today accessing object lists, databases, and XML requires a different syntax for every of these technologies. LINQ (Language Integrated Query) makes it possible to use the same syntax accessing all of these technologies.

In this and some follow-on blog entries I'm showing how LINQ can be used to access object lists, databases, and XML.

With the sample application I have a list of racers List<Racer>. The Racer class is a very simple class that contains the name of the racer and the number of wins. With the result I just want the racers who have won more than three races, and the result should be sorted by the number of wins.

The traditional way (using .NET 2.0) to filter objects from a List<T> is by using the FindAll method passing a predicate. The predicate can be implemented using an anonymous method as shown:

List<Racer> winners = racers.FindAll(
   delegate(Racer r)
   {
      return r.Wins > 3;
   });

Sorting the result is done with the Sort method of List<T>. One overload of Sort accepts a generic delegate Comparison<T> that can be implemented as anonymous method:

winners.Sort(
   delegate(Racer r1, Racer r2)
   {
      return r2.Wins.CompareTo(r1.Wins);
   });

Displaying the resulting collection is done by using the ForEach method passing an Action<T> delegate:

winners.ForEach(
   delegate(Racer r)
   {
      Console.WriteLine("{0}, {1}", r.Name, r.Wins);
   });

C# 2.0 with the generic list class and using anonymous methods makes the filtering and sorting very easy (as soon as you are used to the syntax for anonymous methods). It's even simpler using the LINQ query expression (C# 3.0). The same result shown before can be done with a simple from in where orderby select:

var winners = from r in racers
   where r.Wins > 3
   orderby r.Wins descending
   select r;

foreach (Racer r in winners)
{
   Console.WriteLine("{0}, {1}", r.Name, r.Wins);
}

With the next blog entries I'm showing how to do the same query using a database and XML sources, and what's behind the scenes.

Christian


Italian version of Professional C# 2005

I've just received a copy of my book Professional C# 2005 in Italian language:

 

C# 2005 Guida per lo sviluppatore

http://www.hoepli.it/item.asp?ty=&id=172326&pc=000015003002002

 

All the chapters:

  • L'architettura .NET
  • Le basi del C#
  • Oggetti e tipi
  • Ereditariet√†
  • Operatori e cast
  • Delegate ed eventi
  • Gestione della memoria e puntatori
  • Stringhe ed espressioni regolari
  • Collezioni
  • I generici
  • Reflection
  • Errori ed eccezioni
  • Threading
  • Visual Studio 2005
  • Gli assembly
  • Sicurezza in .NET
  • Localizzazione
  • Distribuzione
  • Accesso ai dati con .NET
  • Programmare .NET con SQL Server 2005
  • Utillizzare XML
  • Lavorare con Active Directory
  • Windows Forms
  • I dati in .NET
  • Grafica con GDI+
  • Pagine ASP.NET
  • Sviluppare in ASP.NET
  • Web Service
  • .NET Remoting
  • Enterprise Service
  • Message Queuing
  • Il futuro della programmazione distribuita
  • Interoperabilit√† con COM
  • Gestione dei file e del registro di sistema
  • Accedere ad Internet
  • Servizi di Windows

 

Christian


Origami Project

Cool animations that don't give too much information about the Origami Project:

The HTML source of this week's information includes this comment:

"Origami Project:  the Mobile PC running Windows XP"

More information and rumours can be found in various Websites, e.g.:

Christian