LINQ Query


With LINQ, you get one way to access all these data sources. Regardless of whether you access object lists, the database, or XML, you use the same syntax. LINQ offers an abstraction to query different data sources.

Object Lists

To query a list of objects to get only racers with the country Brazil, you can use the LINQ query, as shown in the following code segment. Formula1.GetRacers() returns an array of Racer objects. from r declares a variable, r, that is used with the where clause to filter only racers where r.Country == “Brazil” is true. The result is sorted descending by the number of wins (orderby r.Wins descend ing), and finally r is selected. The from in where orderby select statement defines the query; this query is then used with the foreach statement where the list of all racers is filtered and sorted, and foreach iterates through the resulting list. Running the application, you see the same result as when previously accessing the objects.

  private static void LinqObjects() {    var queryBrazilRacers = from r in Formula1.GetRacers()                       where r.Country == "Brazil"                       orderby r.Wins descending                       select r;    foreach (Racer r in queryBrazilRacers)    {       Console.WriteLine("{0:A}", r);    } } 

Relational Data

LINQ to SQL is used for using LINQ queries to access the database. To query the database, the previously created class Racer must be mapped to the Racers table in the database. This can be done either by defining an XML mapping file that defines what property maps to what column, or the mapping can be set by applying attributes to the Racer class. In the sample here, the Racer class is modified with mapping attributes. The attribute [Table] is used to map the class Racer to the table Racers, the [Column] attributes are used to map fields and properties to columns in the table. With the column attribute, you can also define the SQL type of the column in the table and nullability.

 [Serializable] [Table(Name="Racers")] public class Racer : IComparable<Racer>, IFormattable {    public Racer(string firstname, string lastname, string country, int starts,          int wins)    {       this.firstname = firstname;       this.lastname = lastname;       this.country = country;       this.starts = starts;       this.wins = wins;    }    public Racer(string firstname, string lastname, string country, int starts)       : this(firstname, lastname, country, starts, 0) { }    public Racer(string firstname, string lastname, string country)       : this(firstname, lastname, country, 0) { }    public Racer(string firstname, string lastname)       : this(firstname, lastname, "unknown") { }    [Column(Id=true)]    private int id;    private string firstname;    [Column(DBType="NVARCHAR(50)")]    public string Firstname    {       get { return firstname; }       set { firstname = value; }    }    private string lastname;    [Column]    public string Lastname    {       get { return lastname; }       set { lastname = value; }    }    private int wins;    [Column]    public int Wins    {       get { return wins; }       set { wins = value; }    }    private int starts;    [Column]    public int Starts    {       get { return starts; }       set { starts = value; }    }    private string country;    [Column]    public string Country    {       get { return country; }       set { country = value; }    }    //...    } }

To access the database, LINQ defines the DataContext class. In the constructor of this class, you can set the connection string to the database. By invoking the generic method GetTable(), the mapping to the database is set up as it is defined by the mapping attributes in the Racer class. Now the same query as was done previously with the object list is done again to access racers from the database. As the same data is stored in the database as it is with returned with the object list, you get the same result from this query as before.

  private static void LinqSql() {    DataContext context = new DataContext(          @"server=(local);database=Formula1;trusted_connection=true");    Table<Racer> racers = context.GetTable<Racer>();    var queryBrazilRacers = from r in racers                            where r.Country == "Brazil"                            orderby r.Wins descending                            select r;    foreach (Racer r in queryBrazilRacers)    {       Console.WriteLine("{0:A}", r);    } } 

XML

LINQ to XML is the technology to use LINQ querying and filtering XML data. LINQ to XML defines new XML classes in the namespace System.Xml.Linq that are element-based instead of the System.Xml classes that are document-based.

The sample application uses the same XML document that was used earlier with XSLT. The XML document is loaded with the static method Load of the new XElement class. The LINQ query from r in references the racers variable that just mapped to the root element <Racers> inside the Racers.xml document. racers.Elements(“Racer”) references all <Racer> child elements. The variable r now maps to a Racer element. With the where clause, the <Country> child element of <Racer> is accessed to compare it to the country Brazil. orderby specifies the <Wins> child element of <Racer> for a descending sort.

  private static void LinqXml() { Use virtual root for path.    var racers = XElement.Load("../../Racers.xml");    var brazilRacers = from r in racers.Elements("Racer")                       where (string)r.Element("Country") == "Brazil"                       orderby (int?)r.Element("Wins") descending                       select r;    foreach (Racer r in queryBrazilRacers)    {       Console.WriteLine("{0:A}", r);    } } 

Other than the specific access of the XML elements, the syntax for the LINQ query is the same. If XML is used untyped, there’s always the fear of a typo and not knowing the element or attribute names during compile time. The error happens at runtime.

However, if you map the XML data with the help of an XSD file and LINQ to XSD you get strongly typed access for XML. With a mapping, the same query as before can be written as strongly typed:

  var racers = XElement.Load("../../Racers.xml"); var x = from r in racers.Racer         where r.Country == "Brazil"         orderby r.Wins descending         select r; 

In both cases, the result is the same as before with LINQ to objects and LINQ to SQL.

What’s behind this all? How does this syntax work? What are the features offered by this technology? This is explained in the remaining part of this chapter.




Professional C# 2005 with .NET 3.0
Professional C# 2005 with .NET 3.0
ISBN: 470124725
EAN: N/A
Year: 2007
Pages: 427

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net