[Evolution in action] C#1.1=>2.0=>3.0 [LINQ and query expressions]

Makeup Querying Collections

filtering a collection [LINQ]

       static void Main()
       {
           List<Product> products = Product.GetSampleProducts();
           var filtered =
from Product p in products
                                where p.Price > 10
                                select p;
           foreach (Product product in filtered)
           {
               Console.WriteLine(product);
           }
       }

LINQ is what C#3.5 is all about at its heart. In particular, it contains query expressions that allow a declarative style for creating queries on various data sources.


Actually, LINQ is that while query expressions are not particularly suitable for simple task,they're very, very good for more complicated situations that would be hard to read if written out in the equivalent method calls.


Now let's look at a code to join the sample products with the sample suppliers (obviously based on the supplier ID), apply the same price filter as before to the products, sort by supplier name and then product name, and print out the name of  both supplier and product for each match.


*So , in earlier versions of C# it would have been a nightmare to implement. In LINQ, it's almost trivial!

Joing ,filtering , ordering, and projecting
      static void Main()
       
{
           
//Get DataSource

           List<ProductWithSupplierID> products = ProductWithSupplierID.GetSampleProducts();
           List
<Supplier> suppliers =
 Supplier.GetSampleSuppliers(); 

           
//
on p.SupplierID = s.SupplierID 
          
//Error:Expected contextual keyword 'equals'


           var filtered 
= from p in products
                                         join s 
in
 suppliers
                                    on p.SupplierID equals s.SupplierID
                                   
where p.Price > 10

                                   orderby s.Name, p.Name 
                                select 
new
                                
{
                                       SupplierName 
=
 s.Name,
                                       ProductName 
=
 p.Name
                                }
;
           
foreach (var n in
 filtered)
           
{
               Console.WriteLine(
"print out" +
 n.SupplierName, n.ProductName);
           }

       }

It looks remarkably like SQL, This is the reaction of many people on first hearing.

So, we maybe getting data from any number of sources:XML
<?xml version="1.0"?>
<Data>
  
<Products>
    
<Product Name="Company" Price="9.99" SupplierID="1" />
    
<Product Name="Assassins" Price="14.99" SupplierID="2" />
    
<Product Name="Frogs" Price="13.99" SupplierID="1" />
    
<Product Name="Sweeney Todd" Price="10.99" SupplierID="3" />
  
</Products> 

  
<Suppliers>

    
<Supplier Name="Solely Sondheim" SupplierID="1" />
    
<Supplier Name="CD-by-CD-by-Sondheim" SupplierID="2" />
    
<Supplier Name="Barbershop CDs" SupplierID="3" />
  
</Suppliers>
</Data> 

Well,the xml file is simple enough, but what's the best way of extracting the data from it?

Query it? Join on it?

OK, continue


Shows how much work we have to do in
LINQ to XML

  static void Main()
       
{
           XDocument xdoc 
= XDocument.Load("DataSoure.XML"
);
           
///Descendants: Returns a filtered collection of the descendent elements for this document or element,in document order. Only elements that have a matching XName are included in the collection.
           
///按文档顺序返回此文档或元素的经过筛选的子代元素集合。集合中只包括具有匹配 XName 的元素

           var filtered = from p in xdoc.Descendants("Product")
                                join s 
in
 xdoc.Descendants("Supplier")
                                on Convert.ToInt32(p.Attribute(
"SupplierID"))
                               equals (Int32)s.Attribute("SupplierID")
                               
where Convert.ToDecimal(p.Attribute("Price"
)) > 10
                               orderby Convert.ToString(s.Attribute(
"Name"
)),
                                            (String)p.Attribute(
"Name"
)
                               select 
new

                               
{
                                         SupplierName 
= (String)s.Attribute("Name"
),
                                         ProductName 
= (string)p.Attribute("Name"
)
                               }
;
           
foreach (var v in
 filtered)
           
{
               Console.WriteLine(
"print out" +
 v.SupplierName, v.ProductName);
           }

       }

Keyword: XDocument,Descendants,Attribute

Well, it's not quite as straightforward, because we need to tell the system how it should understand the data(in terms of what attributes should be used as what types)


Ok, Let us put the data where it's much more likely to be- in a database.
Shows how much work we have to do in LINQ to SQL
Step one: Create  dbml  
无标题
Step two: Haulage DataTable
1
Step three: Looking

 static void Main()
        
{
            
using (DataContext db = new
 DataContext())
            
{
                var filtered 
= from p in
 db.Products
                                      join s 
in
 db.Suppliers
                                              on p.SupplierID equals s.SupplierID
                                      
where p.Price > 10

                                      orderby s.Name, p.Name
                                      select 
new
                                      
{
                                          SupplierName 
=
 s.Name,
                                          ProductName 
=
 p.Name
                                      }
;
                
foreach (var v in
 filtered)
                
{
                    Console.WriteLine(
"print out" +
 v.SupplierName, v.ProductName);
                }

            }

        }

This code issues a database request, which is basically the query transalted into SQL.

Even though we've expressed the query in C# code, it's been executed as SQL.

We'll see later that the way this query joins isn’t how we’d normally use LINQ to SQL— there's a more relation-oriented way of approaching it when the schema and the entities know about the relationship between suppliers and products.

The result is the same, however, and it shows just how similar LINQ to Objects (the in-memory LINQ operating on collections) and LINQ to SQL can be.


It's important to understand that LINQ is flexible, too: you can write your own
query translators. It’s not easy, but it can be well worth it.

For instance: => LINQ to Amazon

无标题11

Wow LINQ to Everything

So much for this!

posted @ 2008-04-22 22:59  RicoRui  阅读(1512)  评论(3编辑  收藏  举报