LINQ, An IntroLINQ, An Intro Florin−Tudor Cristea, Microsoft Student Partner.

Post on 11-Jan-2016

219 views 3 download

Tags:

Transcript of LINQ, An IntroLINQ, An Intro Florin−Tudor Cristea, Microsoft Student Partner.

LINQ, An IntroFlorin−Tudor Cristea, Microsoft Student Partner

Hello, LINQ!Because “Hello, world!” is so out of fashion.

Inspiration sources

http://students.info.uaic.ro/ ~alexandru.stefan/ materiale/ LINQ.pdfhttp://linqinaction.nethttp://msdn.microsoft.com/ en-us/ vcsharp/ aa336746.aspx

LanguageINtegratedQuery

Software is simple. It boils down to two things: code and data. Writing software is not so simple, and one of the major activities it involves is writing code that deals with data.

LINQ could be the missing link—whether this pun is intended is yet to be discovered—between the data world and the world of general-purpose programming languages.

LINQ unifies data access, whatever the source of data, and allows mixing data from different kind of sources. It allows for query and set operations, similar to what SQL statements offer for databases.

LINQ was designed to be used against any type of object or data source and to provide a consistent programming model for doing so.

http://phplinq.codeplex.com

http://jslinq.codeplex.com

http://quaere.codehaus.org

Once you learn how to use LINQ against an array or a collection, you also know most of the concepts needed to take advantage of LINQ with a database or an XML file.

Programming languages

LINQ building blocks

Expression trees

Query expressions

Standard query

operators

LINQ providersLINQ

to Object

s

Objects

LINQ to XML

XML

LINQ to SQL

RDBMS

LINQ to

DataSet

DataSet

LINQ to

Entities

ADO.NET Entity

Framework

HelloLINQ.csprojhellolinqworldWords of length 9 beautiful wonderfulWords of length 5 hello worldWords of length 4 linqTotal number of chars is 32 (an average of 6,4 per word)

Hello, um… language enhancements!“How much wood could a woodchuck chuck if a woodchuck could chuck wood?” or what makes LINQ tick.

Implicitly typed local variables, which permit the types of local variables to be inferred from the expressions used to initialize them.

Object initializers, which ease construction and initialization of objects.

Lambda expressions, an evolution of anonymous methods that provides improved type inference and conversion to both delegate types and expression trees.

Extension methods, which make it possible to extend existing types and constructed types with additional methods. With extension methods, types aren’t extended but look as if they were.

Anonymous types, which are types automatically inferred and created from object initializers.

HelloLE.csproj

HelloLEContd.csproj

ExtensionMethodsDiscoverability.csproj

LINQ building blocksWarning, headsplosions ahead!

static void DisplayProcesses(){ var processes = Process.GetProcesses() .Where(process => process.WorkingSet64 > 20*1024*1024) .OrderByDescending(process => process.WorkingSet64) .Select(process => new {

process.Id,

Name=process.ProcessName }); ObjectDumper.Write(processes);}

sequences query expressions query operators deferred query exec. expression trees

static void DisplayProcesses(){ var processes = Process.GetProcesses() .Where(process => process.WorkingSet64 > 20*1024*1024) .OrderByDescending(process => process.WorkingSet64) .Select(process => new {

process.Id,

Name=process.ProcessName }); ObjectDumper.Write(processes);}

The GetProcesses method of the System.Diagnostics.Process class returns an array of Process objects. This is not surprising and probably wouldn’t be interesting, except that arrays implement the generic IEnumerable<T> interface. This interface, which appeared with .NET 2.0, is key to LINQ. In our particular case, an array of Process objects implements IEnumerable<Process>.

The IEnumerable<T> interface is important because Where, OrderByDescending, Select, and other standard query operators used in LINQ queries expect an object of this type as a parameter.

public static IEnumerable<TSource> Where<TSource>( this IEnumerable<TSource> source, Func<TSource, Boolean> predicate){ foreach (TSource element in source) { if (predicate(element)) yield return element; }}

// System.Linq.Enumerable

An iterator is an object that allows you to traverse through a collection’s elements. What is named an iterator in .NET is also known as a generator in other languages such as Python, or sometimes a cursor, especially within the context of a database.

An iterator is easy to create: it’s simply a method that returns an enumeration and uses yield return to provide the values.

Iterator.csproj

LINQ queries rely heavily on lazy evaluation (deferred query execution). This is one of the most important concepts in LINQ. Without this facility, LINQ would perform very poorly.

DeferredQueryExecution.csproj

Query operators are not a language extension per se, but an extension to the .NET FCL. Query operators are a set of extension methods that perform operations in the context of LINQ queries. They are the real elements that make LINQ possible.

static void DisplayProcesses(){ var processes = Process.GetProcesses() .Where(process => process.WorkingSet64 > 20*1024*1024) .OrderByDescending(process => process.WorkingSet64) .Select(process => new {

process.Id,

Name=process.ProcessName }); ObjectDumper.Write(processes);}

Call to Where

public static IEnumerable<TSource> Where<TSource>( this IEnumerable<TSource> source, Func<TSource, Boolean> predicate){ foreach (TSource element in source) { if (predicate(element)) yield return element; }}

foreach loop

Filter source

Return elements

Some intermediate operations (such as sorting and grouping) do require the entire source be iterated over. Our OrderByDescending call is an example of this.

We’ve stressed several characteristics of extension methods (Where, etc.):They work on enumerations.They allow pipelined data processing.They rely on delayed execution.All these features make these methods useful to write queries. This explains why these methods are called query operators.

Family Query operators

Filtering OfType, Where

Projection Select, SelectMany

Partitioning Skip, SkipWhile, Take, TakeWhile

Join GroupJoin, Join

Concatenation Concat

Ordering OrderBy, OrderByDescending, Reverse, ThenBy, ThenByDescending

Grouping GroupBy, ToLookup

Set Distinct, Except, Intersect, Union

Conversion AsEnumerable, AsQueryable, Cast, ToArray, ToDictionary, ToList

Equality SequenceEqual

Element

ElementAt, ElementAtOrDefault, First, FirstOrDefault, Last, LastOrDefault, Single, SingleOrDefault

Generation DefaultIfEmpty, Empty, Range, Repeat

Quantifiers All, Any, Contains

Aggregation Aggregate, Average, Count, LongCount, Max, Min, Sum

var processes = Process.GetProcesses() .Where(process => process.WorkingSet64 > 20*1024*1024) .OrderByDescending(process => process.WorkingSet64) .Select(process => new {

process.Id,

Name=process.ProcessName });

var processes = from process in Process.GetProcesses() where process.WorkingSet64 > 20*1024*1024 orderby process.WorkingSet64 descending select new { process.Id, Name=process.ProcessName };

The two code pieces are semantically identical. A query expression is convenient declarative shorthand for code you could write manually. Query expressions allow us to use the power of query operators, but with a query-oriented syntax.

When you use a query expression, the compiler automagically translates it into calls to standard query operators.

from id in source

{ from id in source |

join id in source on expr equals

expr [ into id ] |

let id = expr |

where condition |

orderby ordering, ordering, … }

select expr | group expr by key

[ into id query ]

Starts with from

Zero or more from, join, let,

where, or orderby

Ends with select or group byOptional into

continuation

Use let to declare

temporary variables

Query operator C# syntax

All N/A

Any N/A

Average N/A

CastUse an explicitly typed range variable, for example: from int i in numbers

Count N/A

Distinct N/A

GroupBygroup ... bygroup ... by ... into ...

GroupJoinjoin ... in ... on ...equals ... into ...

Joinjoin ... in ... on ...equals ...

LongCount N/A

Max N/A

Min N/A

Query operator C# syntax

OrderBy orderby

OrderByDescending orderby ... descending

Select select

SelectMany Multiple from clauses

Skip N/A

SkipWhile N/A

Sum N/A

Take N/A

TakeWhile N/A

ThenBy orderby ..., ...

ThenByDescending orderby ..., ... descending

Where where

var authors = from distinctAuthor in ( from book in SampleData.Books where book.Title.Contains("LINQ") from author in book.Authors.Take(1) select author) .Distinct() select new {distinctAuthor.FirstName, distinctAuthor.LastName};

var authors = SampleData.Books .Where(book => book.Title.Contains("LINQ")) .SelectMany(book => book.Authors.Take(1)) .Distinct() .Select(author => new {author.FirstName, author.LastName});

As for expression trees... we’ll cover these later (deferred query execution redux, IQueryable, dynamic queries, abracadabra). Maybe.

System.Core.dllSystemSystem.LinqSystem.Linq.ExpressionsSystem.Data.DataSetExtensions.dllSystem.DataSystem.Data.Linq.dllSystem.Data.LinqSystem.Data.Linq.MappingSystem.Data.Linq.SqlClientSystem.Xml.Linq.dllSystem.Xml.LinqSystem.Xml.SchemaSystem.Xml.XPath

See y’all next time!