LINQ to SQL

LINQ to SQL is an API that allows querying relational databases. The samples in this post are based on the concepts of:

  • Entity classes (which are instances of Entity Types). Such a class is a regular .NET class that is decorated with the attribute Table and its properties and fields with the attribute Column
  • DataContext, is the channel for doing operations with the database; it is used like an ADO.NET connection; actually its constructor takes either a connection string or an ADO.NET connection

Considering the known Winner class from the previous posts,

public class Winner
{
     public string Name { get; set; }
     public string Country { get; set; }
     public int Year { get; set; }
}


Decorating it with Table and column like this

[Table(Name = "Winners")]
public class Winner
{
    [Column]
    public string Name { get; set; }

    [Column]
    public string Country { get; set; }

    [Column(IsPrimaryKey = true)]
    public int Year { get; set; }
}


will create a direct mapping between Winner and the table call Winners, and between the fields Name, Country and Year of the class and the columns with the same name from the table. Both Table and Column have several properties. One of them is Name, which specifies the actual name of the table or column corresponding to the class or property. If the property Name is not specified, the same name as for the class and properties is used.

Assuming we have a SQL Server database, located at C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\UCL.mdf, with a table Winners that has three columns Year (which is also the primary key), Name and Country, and that this table is populated with the winners of UEFA Champions League, we could write the following code to retrieve and show the winners:

public void PrintWinners()
{
     // creates a data context that takes the path of the database
     DataContext dc = new DataContext(@"C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\UCL.mdf");

     // retrieves a Table of Winner
     Table winners = dc.GetTable();

     // creates a sequence of winners ordered descending by the winning year
     var result = from w in winners
                  orderby w.Year descending
                  select w;

     // prints the sequence of winners
     foreach (var w in result)
     {
          Console.WriteLine("{0} {1}, {2}",
          w.Year, w.Name, w.Country);
     }
}


First, we must instantiate a DataContext, passing as argument the path to the database. DataContext has a method GetTable, that returns a Table. To get the winners we call it as shown above. On this table, we can perform a query and show the results:

2006 Barcelona, Spain
2005 Liverpool, England
2004 FC Porto, Portugal
2003 AC Milan, Italy
2002 Real Madrid, Spain
2001 Bayern Munchen, Germany
2000 Real Madrid, Spain
1999 Manchester Utd., England
1998 Real Madrid, Spain
1997 Borussia Dortmund, Germany
1996 Juventus, Italy
1995 AFC Ajax, Netherlands
1994 AC Milan, Italy
1993 Olympique de Marseille, France


It is however recommended that we use a so called strongly-typed version of DataContext. In other words, a derived class from DataContext that keeps as members all the table collections. In this case we don’t have to call directly GetTable<>();

public class UCLDataContext : DataContext
{
    public Table Winners;

    public UCLDataContext(string connection)
      :
      base(connection)
    {}
}


The PrintWinnes function would have to change to:

public void PrintWinners()
{
    // creates a data context that takes the path of the database
    UCLDataContext dc = new UCLDataContext(@"C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\UCL.mdf");

    // creates a sequence of winners ordered descending by the winning year
    var result = from w in dc.Winners
                 orderby w.Year descending
                 select w;

    // prints the sequence of winners
    foreach (var w in result)
    {
        Console.WriteLine("{0} {1}, {2}",
            w.Year, w.Name, w.Country);
    }
}


Only querying the database is not enough. DataContext also allow us to submit changes to the database.

The following function shows how to add a winner to the table Winners:

public void AddWinner()
{
     // creates a data context that takes the path of the database
     UCLDataContext dc = new UCLDataContext(@"C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\UCL.mdf");

     // adds a new winner to the table
     dc.Winners.Add(new Winner { Name = "Manchester United", Country = "England", Year = 2007});

     // submites the changes
     dc.SubmitChanges();
}


If you want for instance to remove all the winners from Spain, we can do the following:

public void DeleteWinner()
{
    // creates a data context that takes the path of the database
    UCLDataContext dc = new UCLDataContext(@"C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\UCL.mdf");

    // remove a sequence of winners
    dc.Winners.RemoveAll(from w in dc.Winners
                      where w.Country == "Spain"
                      select w);

    // submites the changes
    dc.SubmitChanges();
}


Hits for this post: 24180 .

On Saturday, April 22, I delivered a presentation on LINQ at a meeting of the RONUA community in Timisoara. The presentation was focused on sample codes for LINQ to Objects, LINQ to XML and LINQ to SQL. Today I uploaded on the site the presentation and demo programs so that you can download them.

Here is the list of downloads:

  • power point presentation in Romanian (88.5 KB); requires PowerPoint 2007
  • demo programs: a solution with three VC# projects (16.2 KB): LinqToObjects, LinqToXML and LinqToSQL; requires Visual Studio Orcas March CTP; comments are in English
  • UCL database (135 KB): SQL Server 2005 Express database required by the LinqToSQL project

Make sure that in the LinqToSQL project you use the right path for the UCL.mdf file. Please post any kind of comments you might have about it.

Hits for this post: 17646 .

Nu pot sa raman indiferent la ce s-a intamplat ieri in Romania, o tara cu pretentii de apartenenta europeana. Ieri, conjuratia oligarhilor, mafiotilor si certatilor cu legea si bunul simt au incercat sa ucida nu pe Traian Basescu, nu mitul Basescu, ci insusi poporul roman. Pentru ca se s-a intamplat este o lovitura data omului de rand din Romania, care inca mai crede ca nu putem desprinde de apucaturile comuniste, si de tranzitie, unde care baitetii destepti fura, iar baietii prosti inghit.

Nu vreau decat sa citez cateva paragrafe publicate astazi in Evenimentul Zilei.

Grigore Cartianu

Cei 322 de parlamentari care au votat suspendarea unui presedinte in ciuda recomandarii Curtii Constitutionale isi pot face o poza de album, pentru posteritate. Generatii intregi se vor putea desfata astfel privindu-i pe politrucii care, din razbunare, frustrare sau interese de tip sicilian, au pus umarul la decapitarea statului roman. Dumneata, maicuta Anuta, dumneata, taica Vasilica, voi, cetatenii X ai acestei natiuni! Iar mesajul e clar: nu-i suparati pe nemernici, ca va vor executa cu sange rece! Au bani, relatii, televiziuni. Conduc Republica Mafiota Romania. Pe tine, romanule cinstit, te vor strivi ca pe un gandac! A interesat pe vreunul dintre calaii de ieri avizul negativ dat de Curtea Constitutionala? Ori faptul ca romanii, intrebati daca sunt de acord cu suspendarea presedintelui, au raspuns „NU” intr-un procent zdrobitor? Da’ de unde: ucigasul, cand e hotarat sa comita o crima, baga jungherul si in maicuta care l-a nascut. Poate va intrebati cine sunt, de fapt, cei 322 de ispravnici care l-au executat pe seful statului. Avem de-a face cu trei categorii: 1. parlamentarii cu probleme penale (ii regasim din belsug si la PSD, si la PC sau UDMR); 2. marionetele unor afaceristi penali (la loc de frunte: grupurile Patriciu-PNL si Voiculescu-PC); 3. cei ce-si razbuna propriile patimi din timpul regimului Basescu (turnatoriii Felix, Cosea, Stanoiu, Miki Spaga, apologetii comunisti Iliescu, Vadim si Paunescu etc.); 4. adversarii spulberati de Basescu in alegerile trecute (Nastase, Geoana, Oprescu); 5. frustratii care au stat in preajma lui Basescu cat capra la tap (Lavinia Sandru, Gusa, Pavelescu). Asa s-a ajuns la aberatia ca ieri sa voteze suspendarea, cot la cot, bolsevicii (spasiva, tavarisci Iliescu!) cu liberalii si taranistii, dar si PRM-istii cu UDMR-istii. Vladimir Tismaneanu

Profitand de fiecare ambiguitate a sistemului juridic, manipuland semantic prevederile Constitutiei, inventand culpe si scornind cele mai abjecte scenarii menite sa-l compromita pe presedinte, acesti oameni nu fac decat sa-si continue vechile metehne. Votul anti-Basescu a fost unul al infamiei, al oportunismului cras si al panicii. El probeaza cat se poate de elocvent si alarmant prapastia dintre societatea civila, care se identifica tot mai mult cu presedintele Basescu, si o mare parte a clasei politice. Cand spun societate civila ma gandesc, evident, la acele forte care sustin valorile tolerantei, decentei si civilitatii, deci nu la grupuri fundamentalist-xenofobe ori publicatii specializate in viziuni conspirationiste, antiliberale si antisemite. Inamicii lui Traian Basescu nu i-au iertat faptul ca a initiat si sustinut demersul Comisiei de analiza a dictaturii comuniste. De la Dan Voiculescu la Ion Iliescu, de la Vadim Tudor la Sorin Rosca-Stanescu, de la fratii Roncea la „Noua Dreapta”, ca sa nu mai vorbesc de Relu Fenechiu, Ion Cristoiu, Mihai Pelin si Mihai Ungheanu, s-a nascut un val al refuzului asumarii responsabile a trecutului comunist. Traian Basescu a facut-o, iar acest lucru este impardonabil pentru neocomunisti, neotribalisti, neosecuristi si amicii lor oligarhi. Se poarta in Romania o mare batalie politica si morala. Nu ma indoiesc ca vointa suverana a majoritatii poporului roman se va exprima ferm in favoarea lui Traian Basescu. Din acest punct de vedere, singurul care conteaza in perspectiva istorica, puciul parlamentar a esuat. Marius Draghici

“Patrulaterul negru” este dovada tradarii electoratului de catre parlament. Cata ura, cat venin au putut sa curga de la tribuna parlamentului! In numele nostru! Nu ma mir. Oligarhii se regrupeaza usor pentru ca isi recunosc interesele. Noi, cetatenii, mai greu. Din lasitate? Din indiferenta? Din resemnare? Suspendarea presedintelui Traian Basescu este o dovada ca Romania este un stat ingenuncheat de oligarhie. PSD-ul merge mai departe: ia in calcul o lege prin care sa i se interzica lui Basescu sa mai candideze! Este un moment crucial in istoria Romaniei. De el depinde viitorul nostru. Trebuie sa ne regasim reperele valorice, sa ne uitam in istorie. Am invins un dictator, am daramat un sistem sprijinit pe teroare. Daca stam cu mainile incrucisate, nu incepem nesupunerea civica, ne uitam la televizor la mia de oameni din piata, adio! Nu ne ramane decat sa impachetam bruma de democratie pe care am construit-o intr-un sicriu! Este timpul sa spunem: acestea sunt drepturile noastre, iar peste ele nu se poate trece! Vrem egalitate! Vrem ca mafiotii sa stea in spatele gratiilor, cu averea confiscata si redistribuita la popor! Vrem acces la educatie! Democratia inseamna participare, inclusiv in strada. Aveam o alegere de facut, in aceste patru luni. Vom asista pasivi la minciunile politicienilor alesi pe liste sau iesim in strada pentru un presedinte care vrea votul uninominal. Florian Bichir

De data aceasta, poporul poate sa se intrebe ce-i uneste pe complotisti: ura sau ce alte interese? Ce-i leaga pe acesti oameni de formeaza monstruoase coalitii? Iar poporul poate nu va mai plange la Ruginoasa, ci va bea sampanie in Piata Universitatii. De data aceasta trebuie sa le spunem acestor parlamentari: DESTUL! PESTE POPORUL ROMAN NU SE MAI TRECE! NU conteaza cum o facem, prin vot, prin iesire in strada, dar trebuie sa le aratam ca in Romania, pana la urma domneste vointa poporului. Altfel nu suntem decat o tara bananiera.

Hits for this post: 6936 .

In a previous post I explained than when you create a MFC application with the March CTP of ‘Orcas’ and add a command or split button to a dialog, the .rc file is not compiled, because styles such as BS_COMMANDLINK are not found. My workaround for the moment was to redeclare them in the resource.h header. But that is not a good idea, because the IDE overwrites the file, removing what you put there. So, eventually, I brought that up to the VC++ team, and it seems that the March CTP has a problem with the resource headers, used by the resource compilers. In other words, at least commctrl.rc was not updated to contain the required definitions.

You can work around this in two better ways:

  • install the Windows RTM SDK, or
  • redefine the necessary styles in commctrl.rc
    #if _WIN32_WINNT >= 0x0600
    
    // BUTTON STATE FLAGS
    #define BST_DROPDOWNPUSHED      0x0400
    
    // BUTTON STYLES
    #define BS_SPLITBUTTON          0x0000000CL
    #define BS_DEFSPLITBUTTON       0x0000000DL
    #define BS_COMMANDLINK          0x0000000EL
    #define BS_DEFCOMMANDLINK       0x0000000FL
    
    #endif
    

I decided to go for the second, and now the applications are successfully built. I have been told that the problem has been already fixed for the upcoming CTP/beta. The VC++ team will soon post about this on their blog too. I want to thank to Marian Luparu for the help with this matter.

Hits for this post: 13304 .

LINQ to XML

LINQ offers an API called LINQ to XML, formally known as XLinq, that provides support for working with XML. This API resides in the System.Xml.Linq namespace, and you need to add a reference to the assembly with the same name to be able to use it. If you installed the Orcas March CTP bits, the assembly can be found in folder C:\Windows\Microsoft.NET\Framework\v3.5.20209.

In the namespace you can find classes such as XNode, XElement, XAttribute, XText, etc.

XElement implements an XML element. It has several constructor. The following snippet constructs an empty element called winner.

   XElement root = new XElement("winner");
   Console.WriteLine(root.ToString());


The output is

< winner />


Overloaded constructor can take additional parameters. If we pass a string:

XElement root = new XElement("winner", "Manchester Utd.");


We get:

< winner >Manchester Utd.< /winner >


We can also pass an Xattribute

XElement root = new XElement("winner", "Manchester Utd.",
                             new XAttribute("Year", 1999));


Or

XElement root = new XElement("winner", new XAttribute("Year", 1999),
                             "Manchester Utd.");


In this case the winner element will have an attribute called Year having the value 1999, and the text of the element will be Manchester Utd..

< winner Year="1999" >Manchester Utd.< /winner >


We can nest the all these to make a hierarchy of xml elements:

XElement root = new XElement("winners",
                              new XElement("winner",
                                   new XElement("Name", "Barcelona"),
                                   new XElement("Country", "Spania"),
                                   new XElement("Year", 2006)
                              ),
                              new XElement("winner",
                                   new XElement("Name", "Liverpool"),
                                   new XElement("Country", "Anglia"),
                                   new XElement("Year", 2005)
                              )
                );


Of course, the XML elements don’t have to be created like that. They can be dynamically created. One way is using methods like Add, AddFirst, RemoveNodes, etc., methods from the XContainer class.

IEnumerable< Winner > winners = UCL.GetWinners();
XElement root = new XElement("winners");

foreach (Winner w in winners)
{
      root.Add(new XElement("winner",
                             new XElement("Name", w.Name),
                             new XElement("Country", w.Country),
                             new XElement("Year", w.Year)));
}


And we can write this to a file with:

Root.Save("winners.xml");


However, LINQ to XML offers a better way to generate XML content.

IEnumerable< Winner > winners = UCL.GetWinners();

XElement root = new XElement("winners",
                    from w in winners
                    select new XElement("winner",
                                        new XElement("Name", w.Name),
                                        new XElement("Country", w.Country),
                                        new XElement("Year", w.Year)));

The result in this case is the same as above.

XElements has several overloads for saving its content to a file:

public void Save(string fileName);
public void Save(TextWriter textWriter);
public void Save(XmlWriter writer);
public void Save(string fileName, bool preserveWhitespace);
public void Save(TextWriter textWriter, bool preserveWhitespace);


On the other hand, XElement offers several overloaded static methods for loading content from XML files:

public static XElement Load(string uri);
public static XElement Load(TextReader textReader);
public static XElement Load(XmlReader reader);
public static XElement Load(string uri, bool preserveWhitespace);
public static XElement Load(TextReader textReader, bool preserveWhitespace);
public static XElement Parse(string text);
public static XElement Parse(string text, bool preserveWhitespace);


The following code loads the content of the file winners.xml and prints it in the console.

XElement root = XElement.Load("winners.xml");
Console.WriteLine(root.ToString());


Considering that we have in winners.xml the list of UEL winners, we can load the content of this XML file and create Winner objects:

IEnumerable< Winner > winners =
             from e in XElement.Load("winners.xml").Elements("winner")
             select new Winner
                    {
                         Name = (string)e.Element("Name"),
                         Country = (string)e.Element("Country"),
                         Year = (int)e.Element("Year")
                    };

foreach (Winner w in winners)
{
     Console.WriteLine("{0} {1}, {2}", w.Year, w.Name, w.Country);
}


XElement.Load() creates an XElement containing all the elements in the file. Elements() returns only the children called winner (in our case all the children elements of the root). After that we project Winners created by accessing the children of element “winner” in the XML file. The output is

2006 Barcelona, Spania
2005 Liverpool, Anglia
2004 FC Porto, Portugalia
2003 AC Milan, Italia
2002 Real Madrid, Spania
2001 Bayern Munchen, Germania
2000 Real Madrid, Spania
1999 Manchester Utd., Anglia
1998 Real Madrid, Spania
1997 Borussia Dortmund, Germania
1996 Juventus, Italia
1995 AFC Ajax, Olanda
1994 AC Milan, Italia
1993 Olympique de Marseille, Franta


Now suppose you want to project only the names of the winners. In this case we could write:

var winners =
            from e in XElement.Load("winners.xml").Elements("winner")
            select (string)e.Element("Name");

foreach (var w in winners)
{
     Console.WriteLine("{0}", w);
}


The ouput of the program is:

Barcelona
Liverpool
FC Porto
AC Milan
Real Madrid
Bayern Munchen
Real Madrid
Manchester Utd.
Real Madrid
Borussia Dortmund
Juventus
AFC Ajax
AC Milan
Olympique de Marseille


This output however lists a team multiple times. If we want to have these winners listed only once we could apply the Distinct operator on the result and select the winners only once:

var winners =
         from e in XElement.Load("winners.xml").Elements("winner")
         select (string)e.Element("Name");

var winnersDistinct = Enumerable.Distinct(winners);

foreach (var w in winnersDistinct)
{
    Console.WriteLine("{0}", w);
}


The new output would be

Barcelona
Liverpool
FC Porto
AC Milan
Real Madrid
Bayern Munchen
Manchester Utd.
Borussia Dortmund
Juventus
AFC Ajax
Olympique de Marseille


Hits for this post: 22415 .

Since this is a local event, I’ll continue the post in Romanian.

Sambata, 21 Aprilie 2007, la ora 09:00 are loc intalnirea membrilor Ronua din Timisoara, la LTHD Corporation, str. Ardeal, Nr. 70. Agenda evenimentului este:

09:00 – 09:10 – Intro si networking

09:10 – 10:10 – Introducere in LINQ
Marius BANCILA, MVP VC++, SiemensVDO Automotive

10:10 – 10:40 – Pauza

10:40 – 11:40 – Primii pasi in ASP.NET AJAX si ASP.NET AJAX Control Toolkit
Calin Ionel IEPURE, MCP, X3 Studios

11:40 – 12: 00 – Pauza

12:00 – 12:40 – Little used developer tools
Catalin GHEORGHIU,  I Computer Solutions

12:40 – 13: 00 – Pauză

13:00 – … – Discutii libere

Va rugam confirmati participarea aici.

Hits for this post: 6300 .

yield is a new contextual keyword introduced to C# 2.0, vital for lazy evaluation and the performance of queries in LINQ. Being a contextual keyword means that yield can be used as a variable name in C# without any problem. When put before return it becomes a keyword.

yield allows one enumerable class to be implemented in terms of another. This enables the delay of execution of queries until the latest possible moment, skipping the generation of intermediate results that would drastically reduce poerformance. The query operators in LINQ operate on sequence. The result of a query is often another sequence. Lazy evaluation means that until you iterate over the result of the query, the source of the query is not iterated.

To show you how yield works, let’s consider the same class I used in my last post, Winner.

public class Winner
{
    string _name;
    string _country;
    int _year;

    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
    public string Country
    {
        get { return _country; }
        set { _country = value; }
    }
    public int Year
    {
        get { return _year; }
        set { _year = value; }
    }
    public Winner(string name, string country, int year)
    {
       _name = name;
       _country = country;
       _year = year;
    }
}


and create a class WinnerDB, that contains a list of UEFA Champion League winners. This class implements IEnumerable and returns an enumerator, WinnerEnumerator, to be able to iterate over the winners.

    public class WinnerEnumerator : IEnumerator
    {
        int pos = -1;
        private Winner[] _winners;
        public WinnerEnumerator(Winner[] winners)
        {
            _winners = winners;
        }

        public void Reset()
        {
            pos = -1;
        }

        public bool MoveNext()
        {
            pos++;
            return (pos < _winners.Length);
        }

        public object Current
        {
            get
            {
                try
                {
                    return _winners[pos];

                }
                catch (IndexOutOfRangeException)
                {
                    throw new InvalidOperationException();
                }
            }
        }
    }

    public class WinnersDB : IEnumerable
    {
        private Winner[] _winners;
        public WinnersDB()
        {
            _winners = new Winner[]
            {
                new Winner("Barcelona", "Spain", 2006),
                new Winner("Liverpool", "England", 2005),
                new Winner("FC Porto", "Portugal", 2004),
                new Winner("AC Milan", "Italy", 2003),
                new Winner("Real Madrid", "Spain", 2002),
                new Winner("Bayern Munchen", "Germany", 2001),
                new Winner("Real Madrid", "Spain", 2000),
                new Winner("Manchester Utd.", "England", 1999),
                new Winner("Real Madrid", "Spain", 1998),
                new Winner("Olimpique Marseille", "France", 1993),
            };
        }

        public IEnumerator GetEnumerator()
        {
            return new WinnerEnumerator(_winners);
        }
    }


The usage of this class would look like this:

    class Program
    {
        static void Main(string[] args)
        {
            WinnersDB db = new WinnersDB();
            foreach (Winner w in db)
            {
                Console.WriteLine("{0}\t{1}, {2}",
                    w.Year, w.Name, w.Country);
            }
        }
    }


and the output of the program

2006    Barcelona, Spain
2005    Liverpool, England
2004    FC Porto, Portugal
2003    AC Milan, Italy
2002    Real Madrid, Spain
2001    Bayern Munchen, Germany
2000    Real Madrid, Spain
1999    Manchester Utd., England
1998    Real Madrid, Spain
1993    Olimpique Marseille, France


So far so good. But with yield, you can let the compiler do all that stuff for you. When you use yield, the compiler generates an enumerator that keeps the current state of the iteration.

class Program
{
    public static IEnumerable WinnersDB()
    {
        Winner [] winners = new Winner[]
        {
                new Winner("Barcelona", "Spain", 2006),
                new Winner("Liverpool", "England", 2005),
                new Winner("FC Porto", "Portugal", 2004),
                new Winner("AC Milan", "Italy", 2003),
                new Winner("Real Madrid", "Spain", 2002),
                new Winner("Bayern Munchen", "Germany", 2001),
                new Winner("Real Madrid", "Spain", 2000),
                new Winner("Manchester Utd.", "England", 1999),
                new Winner("Real Madrid", "Spain", 1998),
                new Winner("Olimpique Marseille", "France", 1993),
        };

        foreach (Winner w in winners)
        {
            yield return w;
        }
    }

    static void Main(string[] args)
    {
        foreach (Winner w in WinnersDB())
        {
            Console.WriteLine("{0}\t{1}, {2}",
                w.Year, w.Name, w.Country);
        }
    }
}


Running this code will produce the same output as the previous one, except that the implementation is much simpler. Perhaps the example is not the best, but should give you a hint of the use of the yield keyword. To see that the source is actually iterated only when the result is iterated, we can modify the WinnersDB method to print a message in the console:

foreach (Winner w in winners)
{
    Console.WriteLine("yield: {0} {1}, {2}", w.Year, w.Name, w.Country);
    yield return w;
}


In this case, the output looks like this:

yield: 2006 Barcelona, Spain
2006    Barcelona, Spain
yield: 2005 Liverpool, England
2005    Liverpool, England
yield: 2004 FC Porto, Portugal
2004    FC Porto, Portugal
yield: 2003 AC Milan, Italy
2003    AC Milan, Italy
yield: 2002 Real Madrid, Spain
2002    Real Madrid, Spain
yield: 2001 Bayern Munchen, Germany
2001    Bayern Munchen, Germany
yield: 2000 Real Madrid, Spain
2000    Real Madrid, Spain
yield: 1999 Manchester Utd., England
1999    Manchester Utd., England
yield: 1998 Real Madrid, Spain
1998    Real Madrid, Spain
yield: 1993 Olimpique Marseille, France
1993    Olimpique Marseille, France


Hits for this post: 24167 .

I just came across this great site, http://www.mintrubbing.org/, the “official site” of Romanian Mint Rubbing Association. Mint rubbing is:

mint rubbing (from Romanian “a freca menta”) – time and life management technique developed in Romania and practiced by millions of people worldwide.

This site is dedicated to provide you all the resources need to put to use the wonderful effects of rubbing mint.

The testimonials are also rocking:

Dear Sir, Greetings from Romania! I’ve just found out about your efforts to get this ancient and wonderfull ancient Romanian art of “mint rubbing” known all over the world. I consider it one of the most intriguing and most pleasant arts in the world. It is a pitty that it is not (yet!) an Olimpic contest! I wish you more and more visitors and, with the help of others, to raize this art to the perfection. (claudiu)

I would like to join your respectable organization and receive montly publications about the most efficient methods of mint rubbing, because this is the only thing I can do, and I want to excel in this field. My dream is to rub mint like no man rubbed it before. (victor)

RMRA is one of the best things that happened to Romania. (alex)

The site also features a list of Romanian ancient wisdom. One that I like very much is this:

achievement

Don’t miss the site!

Hits for this post: 11215 .

Have you ever wondered how many words the Visual Studio IDE has? Or how many words are in the documentation? Well, according to Fabrice Fonk from the MSDN DevWiki project, the numbers are:

  • 1 million words for the IDE
  • over 50 million words in the documentation

You can hear it from himself in this video.

Hits for this post: 5911 .

In my last post about LINQ I shown you an example about how to use the language integrated query to select information about directories. In this post I’ll get more into the syntax and show you something about the functional querying style.

My examples will focus on displaying information about UEFA Champions Leage winners. Thus, I have created a class called Winner that looks this this:

class Winner
{
    string  _name;
    string  _country;
    int     _year;

    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
    public string Countryr
    {
        get { return _country; }
        set { _country = value; }
    }

    public int Year
    {
        get { return _year; }
        set { _year = value; }
    }

    public Winner(string name, string country, int year)
    {
        _name = name;
        _country = country;
        _year = year;
    }
};


Also I have created a utility class that returns a list (incomplete) of UCL winners:

class UCL
{
    public static IEnumerable GetWinners()
    {
        Winner [] winners =
        {
            new Winner("Barcelona", "Spain", 2006),
            new Winner("Liverpool", "England", 2005),
            new Winner("FC Porto", "Portugal", 2004),
            new Winner("AC Milan", "Italy", 2003),
            new Winner("Real Madrid", "Spain", 2002),
            new Winner("Bayern Munchen", "Germany", 2001),
            new Winner("Real Madrid", "Spain", 2000),
            new Winner("Manchester Utd.", "England", 1999),
            new Winner("Real Madrid", "Spain", 1998),
            new Winner("Olimpique Marseille", "France", 1993),
        };

        return winners;
    }
};


Now, let’s see how we could display all this info ascending by the year of winning:

IEnumerable winners = UCL.GetWinners();
var result = from w in winners
             orderby w.Year
             select w;

foreach (var w in result)
{
    Console.WriteLine("{0}\t{1}, {2}",
            w.Year, w.Name, w.Country);
}


That lists the following:

1993    Olimpique Marseille, France
1998    Real Madrid, Spain
1999    Manchester Utd., England
2000    Real Madrid, Spain
2001    Bayern Munchen, Germany
2002    Real Madrid, Spain
2003    AC Milan, Italy
2004    FC Porto, Portugal
2005    Liverpool, England
2006    Barcelona, Spain


This SQL-like syntax is however only a “shell” over the functional syntax. It’s just like with the foreach statement. To be able to iterate with foreach, the collection must implement IEnumerable, which has a method that returns a class that implements IEnumerator. What the compiler is doing when using foreach is calling GetEnumerator to get an iterator, and then Reset() on it, and inserts a while(iterator.MoveNext()), using Current to access the current object from the collection. The same happens here with the declarative query syntax.

Now, let’s suppose we want to list only the winners from England. What we have to do is adding a filtering:

var result = from w in winners
             orderby w.Year
             where w.Country == "England"
             select w;


What I wrote above is actually the same with:

var result = winners.
               OrderBy(w => w.Year).
               Where(w => w.Country == "England").
               Select(w => w);


Here we used the operators OrderBy, Where and Select. These are two of the query operators that allow you to perform filtering, projection and key extraction. These are built of the concept of Lambda expression, which are similar to the CLR delegates. We could rewrite the last query list this:

Func filter = w => w.Country == "England";
Func criteria = w => w.Year;
Func project = w => w;

var result = winners.OrderBy(criteria).Where(filter).Select(project);


OrderBy and OrderByDescending are operators that impose a partial order over the keys. Operators ThenBy and ThenByDescending are used to apply additional sorting criteria by only on sorted sequences (SortedSequence).

Where is used to exclude items from the collection.

Select and SelectMany are operators for projecting only those fields or info that is wanted.

Now, let’s try something more complicated: grouping the winners by country, and inside each group ascending by the winning year. In declarative syntax that would be like this:

var result = from w in winners
             orderby w.Year
             group w.Name by w.Country into groups
             orderby groups.Key
             select groups;

foreach (var w in result)
{
     Console.WriteLine("\n{0}", w.Key);

     foreach (var e in w)
     {
        Console.WriteLine("{0}", e);
     }
}


Enagland
Manchester Utd.
Liverpool

France
Olimpique Marseille

Germany
Bayern Munchen

Italy
AC Milan

Portugal
FC Porto

Spain
Real Madrid
Real Madrid
Real Madrid
Barcelona


In functional programming syntax, the same query is written as:

var result = winners.
                  OrderByDescending(w => w.Year).
                  GroupBy(w => w.Country, w => w.Name).
                  OrderBy(w => w.Key).
                  Select(w => w);



The GroupBy operator imposes a partitioning over a sequence of values based on a key extraction function. It returns a sequence of Grouping values, which contains both the key as well as the group of values mapped to the key. The interface of Grouping is:

public sealed class Grouping{
  public Grouping(K key, IEnumerable group);
  public Grouping();
  public K Key {get; set;}
  public IEnumerable Group {get; set;}
}


You may wonder why the declarative syntax starts with the from clause. The SQL language has a problem, i.e. the order of clauses is not natural. Select is the first by at the time of selecting, you don’t know where do you select from. The from clause is naturally the first one, and this was rectified in LINQ. You always have to put from as the first clause in a query (when using the declarative syntax). In the functional syntax you can see you have to apply the operators on a collection, a sequence of items (in our case winners). That is the functional equivalent of from.

Hits for this post: 16948 .