linq, an intro

47
LINQ, An Intro Florin−Tudor Cristea, Microsoft Student Partner

Upload: moesha

Post on 23-Feb-2016

35 views

Category:

Documents


0 download

DESCRIPTION

LINQ, An Intro. Florin−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.pdf http://linqinaction.net http://msdn.microsoft.com/ en-us/ - PowerPoint PPT Presentation

TRANSCRIPT

Slide 1

LINQ, An IntroFlorinTudor Cristea, Microsoft Student PartnerHello, 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.aspxLanguageINtegratedQuerySoftware 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 linkwhether this pun is intended is yet to be discoveredbetween 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.orgOnce 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.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 arent extended but look as if they were.Anonymous types, which are types automatically inferred and created from object initializers.

HelloLE.csproj

HelloLEContd.csproj

ExtensionMethodsDiscoverability.csprojLINQ 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 treesstatic 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 wouldnt be interesting, except that arrays implement the generic IEnumerable interface. This interface, which appeared with .NET 2.0, is key to LINQ. In our particular case, an array of Process objects implements IEnumerable.The IEnumerable 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 Where( this IEnumerable source, Func predicate){ foreach (TSource element in source) { if (predicate(element)) yield return element; }}

// System.Linq.EnumerableAn iterator is an object that allows you to traverse through a collections 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: its simply a method that returns an enumeration and uses yield return to provide the values.

Iterator.csprojLINQ 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.csprojQuery 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 Wherepublic static IEnumerable Where( this IEnumerable source, Func predicate){ foreach (TSource element in source) { if (predicate(element)) yield return element; }}foreach loopFilter sourceReturn elementsSome intermediate operations (such as sorting and grouping) do require the entire source be iterated over. Our OrderByDescending call is an example of this.Weve 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.FamilyQuery operatorsFilteringOfType, WhereProjectionSelect, SelectManyPartitioningSkip, SkipWhile, Take, TakeWhileJoinGroupJoin, JoinConcatenationConcatOrderingOrderBy, OrderByDescending, Reverse, ThenBy, ThenByDescendingGroupingGroupBy, ToLookupSetDistinct, Except, Intersect, UnionConversionAsEnumerable, AsQueryable, Cast, ToArray, ToDictionary, ToListEqualitySequenceEqualElementElementAt, ElementAtOrDefault, First, FirstOrDefault, Last, LastOrDefault, Single, SingleOrDefaultGenerationDefaultIfEmpty, Empty, Range, RepeatQuantifiersAll, Any, ContainsAggregationAggregate, Average, Count, LongCount, Max, Min, Sumvar 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 fromZero or more from, join, let, where, or orderbyEnds with select or group byOptional into continuationUse let to declare temporary variablesQuery operatorC# syntaxAllN/AAnyN/AAverageN/ACastUse an explicitly typed range variable, for example: from int i in numbersCountN/ADistinctN/AGroupBygroup ... bygroup ... by ... into ...GroupJoinjoin ... in ... on ...equals ... into ...Joinjoin ... in ... on ...equals ...LongCountN/AMaxN/AMinN/AQuery operatorC# syntaxOrderByorderbyOrderByDescendingorderby ... descendingSelectselectSelectManyMultiple from clausesSkipN/ASkipWhileN/ASumN/ATakeN/ATakeWhileN/AThenByorderby ..., ...ThenByDescendingorderby ..., ... descendingWherewherevar 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... well 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.XPathSee yall next time!