LinQ Introduction

  • View

  • Download

Embed Size (px)


LinQ Introduction. Outline. Goals of LinQ Anatomy of a LinQ query More expression examples LinQ to Objects LinQ to XML LinQ to SQL. Goals of LinQ. Integrate data queries into .Net languages - PowerPoint PPT Presentation

Text of LinQ Introduction

PowerPoint Presentation

1LinQ IntroductionOutlineGoals of LinQAnatomy of a LinQ queryMore expression examplesLinQ to ObjectsLinQ to XMLLinQ to SQL2Goals of LinQIntegrate data queries into .Net languagesBefore C# 3.0 you could use delegates, extension methods, anonyous methods and Visitor Pattern to make something similar to LinQ.But the syntax is messy and key points, eg. selection criteria, are not easy to read.3

Goals of LinQProvide a standardized way to query dataChallenges:Different data typesDifferent data representations (xml, sql, objects)Data organization Hierarchical xml (and object)Relational sqlBefore LinQ you should use different apis for accessing databases, objects and xmlLinQ provides one single way (nearly) to access it allLinQ works on collections that implements IEnumerable(the .Net language must therefore support generics)

4Anatomy of a LinQ queryAn example:5string[] characters = { "Donald", "Mickey", "Goofy", "Minnie", "Daisy", "Scrooge" };

IEnumerable query = from c in characters where c.StartsWith("M")!=true orderby c descending select c;

foreach(string s in query)Console.WriteLine(s);

The collection is here a simple string arrayBut the same query will run for more complex objects, SQL, XML etc. DemoWith objects

After demo, note the following:IntellisenseStatic type checking6Query ExpressionsTypes of expressionsFilteringe.g. WhereProjectionse.g. SelectJoininge.g. JoinPartitioninge.g Skip and TakeOrderinge.g OrderByAggregatione.g. Count and Sum

7ProvidersThe same expresions works on different kinds of dataThis is done by accessing a providerA LinQ provider is a gateway to a querable type.There are several builtin providers ObjectsSQLXMLActive DirectoryPLINQ (Parallel processing)Etc.And many custom providers too:LinQ to AmazonLinQ to TwitterEtc.8How are people in Aalborg ?Twitter demoGet LinqToTwitter here: 9 var twitterCtx = new TwitterContext();.. var queryResults = from search in twitterCtx.Search where search.Type == SearchType.Search && search.Attitude == Attitude.Positive && search.GeoCode == "57.028811,9.917771,25km" select search;

foreach (SearchEntry entry in srch.Results) Console.WriteLine(entry.Text);Deferred ExecutionNormally the query is not executed before the result is neededThis is when only lazy operators (where, orderby...) are used.When busy operators are used, the query is executed immediately (count, average) 10 var adults = from p in personList where p.Age > 18 orderby p.Age select (p.FirstName + " " + p.LastName); Console.WriteLine(adults.Count()); personList.Add(new Person { FirstName = Ib", LastName = Madsen", Age = 35 }); foreach (var p in adults) { Console.WriteLine(p.ToString()); }Composed QueriesA composed query is a query that uses another query.In behind LinQ will make new query that is optimized for the given data store (objects, sql, xml...)

11 var adults = from p in personList where p.Age > 18 orderby p.Age select (p.FirstName + " " + p.LastName);..... var query = from p in adults where p.StartsWith("B") select p; foreach (var p in query) Console.WriteLine(p);Encapsulate QueryIt is not possible directly to return an anonymous typeAnd it wouldnt be nice either Therefore it not is possible to return a query if is declared as varThe nice way here is to declare the query as an IEnumerable and return that.If the query is a join or a projection etc. then make a class that maps the output from select and return a collection of objects of that class

12Collections of objectsWe already seen how to access a collection of objectsthis is called LinQ to objectsLinQ to objects is a good alternative to foreach and other iterations13

Custom providersAnd we have seen use of a custom provider to access a webservice.

14If it is a plain webservice that returns a collection, then we could have accessed that with LinQ to objects

In the next part, we will see how to access XML and SQLServer.

15LinQ to XMLUses the System.Xml.Linq namespaceIs somewhat different from other xml apisThe XElement class is the key class.When instanizing a XElement you can generate the whole document in the constructor16 XElement doc = new XElement("Inventory", new XElement("Car", new XAttribute("ID","1000"), new XElement("Color", "Red"), new XElement("Make", "Ford")) ); Red Ford Use LinQ to generate XML17 XElement personDoc = new XElement("People", from c in personList orderby c.LastName select new XElement("Person", new XAttribute("Age", c.Age), new XElement("FirstName", c.FirstName), new XElement("LastName", c.LastName) ));

Caroline Bendtsen Bjarne Hansen ...Use LinQ to search in XML18 XElement doc = MakeXElementFromList(); var query = from p in doc.Elements("Person") where Convert.ToInt32(p.Attribute("Age").Value) < 40 select p; foreach (var p in query) Console.WriteLine(p.Value);LinQ to SQLLinQ accesses the sql db through a datacontext classThe class can be created with a wizard in VisualStudio,where you select which tables to accessOnly SQLServer is supported from MicrosoftBut dbms vendors like Oracle are also providing support for LinQ. (havent tested it myself).An (better?) alternative is to use the Entity Framework19Use the wizard to create the DataContext classAdd a new item to the project using the LINQ to SQL classes template.Select the database and the tables that shall be available20

Select the tablesNote that wizard knows the carnalities


Using LinQ to SQLSelect orders from a certain customer22 NorhwindDataContext dc = new NorhwindDataContext(); var orders = from o in dc.Orders where o.CustomerID == "ALFKI" orderby o.OrderDate select o.OrderID;

foreach (var o in orders) Console.WriteLine(o);SELECT [t0].[OrderID]FROM [dbo].[Orders] AS [t0]WHERE [t0].[CustomerID] = @p0ORDER BY [t0].[OrderDate]

A joinWrite products that the customer has brought23 var orders = from o in dc.Order_Details join p in dc.Products on o.ProductID equals p.ProductID where o.Order.CustomerID == "ALFKI" orderby o.Order.OrderDate select new { product = p.ProductName, orderDate = o.Order.OrderDate };foreach (var p in orders) Console.WriteLine("{0:dd-MM-yyyy}: {1}", (DateTime)p.orderDate, p.product);{SELECT [t1].[ProductName] AS [product], [t2].[OrderDate] AS [orderDate]FROM [dbo].[Order Details] AS [t0]INNER JOIN [dbo].[Products] AS [t1] ON [t0].[ProductID] = [t1].[ProductID]INNER JOIN [dbo].[Orders] AS [t2] ON [t2].[OrderID] = [t0].[OrderID]WHERE [t2].[CustomerID] = @p0ORDER BY [t2].[OrderDate]}JoinJoin is similar to Inner Join in SQLThat means that it is the intersection between two sequencesThe inner sequence is a keyed collection, that makes it a lot faster than a subquery (or traversing in a nested loop)Note that it uses Equals instead of == (remember the difference?)24Group

Group transforms a sequence into a sequence of groups that contains a subsequence25 var products = from p in dc.Products group p by p.Category.CategoryName;

foreach (var group in products) { Console.WriteLine("\nCategory: {0}", group.Key); foreach (var product in group) Console.WriteLine(product.ProductName);Use objects as keysIt is possible to use objects as keys.It can be of an anonymous type or of a defined class

26 var products = from p in dc.Products group p by new { cname = p.Category.CategoryName, cid = p.Category.CategoryID } into productCategories orderby productCategories.Key.cid select productCategories;

foreach (var group in products){ Console.WriteLine("\nID: {0} Category: {1}", group.Key.cid,group.Key.cname); foreach(var product in group) Console.WriteLine(product.ProductName);}Group into27Group will end the query. Use Into to continue the query var products = from p in dc.Products group p by p.Category.CategoryName into productCategories orderby productCategories.Key select productCategories; foreach (var group in products) { Console.WriteLine("\nCategory: {0}", group.Key); foreach (var product in group) Console.WriteLine(product.ProductName);

Grouping and projectingMake a projection on the content of the group28 var products = from p in dc.Products group p by p.Category into productCategories where productCategories.Count() < 8 orderby productCategories.Key.CategoryName select new { cname = productCategories.Key.CategoryName, count = productCategories.Count() }; foreach (var group in products) { Console.WriteLine("Category: {0}, Count: {1}", group.cname,group.count); }Nested queriesNested queries are similar to nested SELECT in SQL.But be careful: O(n2)29 var products = from p in dc.Products where p.CategoryID == (from c in dc.Categories where c.CategoryName == "Seafood" select c).First().CategoryID select p;