90
Language Integrated Query in .NET (LINQ) Extension Methods, Lambda Expressions, LINQ Operators, Expressions, Projections, Aggregations Svetlin Nakov Telerik Corporation www.telerik. com http://schoolacademy.telerik.com

Language Integrated Query in .NET (LINQ)

  • Upload
    gary

  • View
    89

  • Download
    0

Embed Size (px)

DESCRIPTION

Language Integrated Query in .NET (LINQ). Extension Methods, Lambda Expressions, LINQ Operators, Expressions, Projections, Aggregations. http://schoolacademy.telerik.com. Svetlin Nakov. Telerik Corporation. www.telerik.com. Table of Contents. Extension Methods Anonymous Types - PowerPoint PPT Presentation

Citation preview

LINQ and LINQ-to-SQL

Language Integrated Query in .NET (LINQ) Extension Methods, Lambda Expressions, LINQ Operators, Expressions, Projections, AggregationsSvetlin Nakov

Telerik Corporation

www.telerik.com

http://schoolacademy.telerik.com*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*1##Table of ContentsExtension MethodsAnonymous Types Lambda ExpressionsLINQ Building BlocksQuery Operators and ExpressionsQuery Expression TreesLINQ to Objects: Querying CollectionsProjection, Conversion, AggregationSorting, Grouping, Joins, Nested Queries2

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*2##Extension Methods

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*3##Extension MethodsOnce a type is defined and compiled into an assembly its definition is, more or less, finalThe only way to update, remove or add new members is to recode and recompile the codeExtension methods allow existing compiled types to gain new functionalityWithout recompilationWithout touching the original assembly4

Defining Extension MethodsExtension methodsDefined in a static classDefined as staticUse this keyword before its first to specify the class to be extendedExtension methods are "attached" to the extended classCan also be called from statically through the defining static class5Extension Methods Examples6public static class Extensions{ public static int WordCount(this string str) { return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length; }} ...static void Main(){ string s = "Hello Extension Methods"; int i = s.WordCount(); Console.WriteLine(i);}Extension Methods Examples (2)7public static void IncreaseWidth( this IList list, int amount){ for (int i = 0; i < list.Count; i++) { list[i] += amount; }}...static void Main(){ List ints = new List { 1, 2, 3, 4, 5 }; ints.IncreaseWidth(5); // 6, 7, 8, 9, 10}Extension MethodsLive Demo

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*8##Anonymous Types

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*9##Anonymous TypesAnonymous typesEncapsulate a set of read-only properties and their value into a single objectNo need to explicitly define a type firstTo define an anonymous typeUse of the new var keyword in conjunction with the object initialization syntax10var point = new { X = 3, Y = 5 };Anonymous Types ExampleAt compile time, the C# compiler will autogenerate an uniquely named classThe class name is not visible from C#Using implicit typing (var keyword) is mandatory11// Use an anonymous type representing a carvar myCar = new { Color = "Red", Brand = "BMW", Speed = 180 };Console.WriteLine("My car is a {0} {1}.", myCar.Color, myCar.Brand);Anonymous Types PropertiesAnonymous types are reference types directly derived from System.ObjectHave overridden version of Equals(), GetHashCode(), and ToString()Do not have == and != operators overloaded12var p = new { X = 3, Y = 5 };var q = new { X = 3, Y = 5 };Console.WriteLine(p == q); // falseConsole.WriteLine(p.Equals(q)); // trueArrays of Anonymous TypesYou can define and use arrays of anonymous types through the following syntax:13var arr = new[] { new { X = 3, Y = 5 }, new { X = 1, Y = 2 }, new { X = 0, Y = 7 }};foreach (var item in arr){ Console.WriteLine("({0}, {1})", item.X, item.Y);}Anonymous TypesLive Demo

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*14##Lambda Expressions

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*15##Lambda ExpressionsA lambda expression is an anonymous function containing expressions and statementsUsed to create delegates or expression tree typesAll lambda expressions use the lambda operator =>, which is read as "goes to"The left side of the lambda operator specifies the input parametersThe right side holds the expression or statement 16Lambda Expressions ExamplesUsually used with collection extension methods like FindAll() and Count()17List list = new List() { 1, 2, 3, 4 };List evenNumbers = list.FindAll(x => (x % 2) == 0);foreach (var num in evenNumbers){ Console.Write("{0} ", num);}Console.WriteLine();// 2 4

list.RemoveAll(x => x > 3); // 1 2 3Sorting with Lambda Expression18var pets = new Pet[]{ new Pet { Name="Sharo", Age=8 }, new Pet { Name="Rex", Age=4 }, new Pet { Name="Strela", Age=1 }, new Pet { Name="Bora", Age=3 }};var sortedPets = pets.OrderBy(pet => pet.Age);foreach (Pet pet in sortedPets){ Console.WriteLine("{0} -> {1}", pet.Name, pet.Age);}Lambda Code ExpressionsLambda code expressions:19List list = new List() { 20, 1, 4, 8, 9, 44 };

// Process each argument with code statementsList evenNumbers = list.FindAll((i) => { Console.WriteLine("value of i is: {0}", i); return (i % 2) == 0; });

Console.WriteLine("Your even numbers are:");foreach (int even in evenNumbers) Console.Write("{0}\t", even);Delegates Holding Lambda FunctionsLambda functions can be stored in variables of type delegateDelegates are typed references to functionsStandard function delegates in .NET:Func, Func, Func,

20Func boolFunc = () => true;Func intFunc = (x) => x < 10;if (boolFunc() && intFunc(5)) Console.WriteLine("5 < 10");Lambda ExpressionsLive Demo

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*21##LINQ and Query Keywords

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*22##LINQ and Query KeywordsLanguage Integrated Query (LINQ) query keywordsfrom specifies data source and range variablewhere filters source elementsselect specifies the type and shape that the elements in the returned sequencegroup groups query results according to a specified key valueorderby sorts query results in ascending or descending order23Query Keywords Examplesselect, from and where clauses:24int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

var querySmallNums = from num in numbers where num < 5 select num;

foreach (var num in querySmallNums){ Console.Write(num.ToString() + " ");}// The result is 4 1 3 2 0

Query Keywords Examples (2)Nested queries:25string[] towns = { "Sofia", "Varna", "Pleven", "Ruse", "Bourgas" };

var townPairs = from t1 in towns from t2 in towns select new { T1 = t1, T2 = t2 };

foreach (var townPair in townPairs){ Console.WriteLine("({0}, {1})", townPair.T1, townPair.T2);}

Query Keywords Examples (3)Sorting with rderby:26string[] fruits = { "cherry", "apple", "blueberry", "banana" };

// Sort in ascending sortvar fruitsAscending = from fruit in fruits orderby fruit select fruit;

foreach (string fruit in fruitsAscending){ Console.WriteLine(fruit);}

LINQ Query KeywordsLive Demo

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*27##

LINQ Building Blocks

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*28##LINQ Building BlocksSoftware developers spend a lot of time to obtain and manipulate dataData can be stored inCollectionsDatabasesXML documentsetc...As of .NET 3.5 developers can use LINQ a simplified approach to data manipulation29

LINQ Building Blocks (2)LINQ is a set of extensions to .NET FrameworkEncompasses language-integrated query, set, and transform operationsConsistent manner to obtain and manipulate "data" in the broad sense of the termQuery expressions can be defined directly within the C# programming languageUsed to interact with numerous data typesConverted to expression trees at compile time and evaluated at runtime30LINQ Building Blocks (3)LINQ allows query expressions to manipulate:Any object implementing IEnumerableCollections of objectsRelational databasesXML documentsThe query expressions are based on numerous SQL-like query operatorsIntentionally designed to look and feel very similar to SQL expressions31LINQ Building Blocks (4) "LINQ" is the term used to describe this overall approach to data accessLINQ to ObjectsLINQ over objects implementing IEnumerableLINQ to SQL and LINQ to Entities implement LINQ over relational dataLINQ to DataSet is a superset of LINQ to SQLLINQ to XML is LINQ over XML documents32LINQ to *33LINQ enabled data sources

LINQ to ObjectsObjects

LINQto XML

XMLLINQ enabled ADO.NET

LINQ to DataSets

LINQto SQL

LINQ toEntitiesRelational Data

Others

C#

VB.NET

.NET Language-Integrated Query (LINQ)Query OperationsAll LINQ query operations consist of three distinct actions:Obtain the data sourceCreate the queryExecute the query34

LINQ Sequences*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*35##IEnumerable and SequencesThe interface IEnumerable is universal LINQ data sourceImplemented by arrays and all .NET generic collectionsEnables enumerating over a collection of elementsA sequence in LINQ means a collection implementing the IEnumerable interfaceAny variable declared as IEnumerable for type T is considered a sequence of type T36IEnumerable and Sequences (2)Most of the Standard Query Operators are extension methods in the static class System.Linq.EnumerablePrototyped with an IEnumerable as their first argumentE.g. Min(IEnumerable), Where(IEnumerable, Func)Use the Cast or OfType operators to perform LINQ queries on legacy, non-generic .NET collections37

Query Operators and Expressions

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*38##LINQ Query ExpressionsWhen you have a collection of data, a common task is to extract a subset of items based on a given requirementYou want to obtain only the items with names that contain a numberOr dont have embedded spacesLINQ query expressions can greatly simplify the processQuery expressions are written in a declarative query syntax introduced in C# 3.0 39LINQ Query Expressions (2)LINQ query expressions are written in a declarative SQL-like syntaxExample: extracting a subset of array containing items with names of more than 6 characters:40string[] games = {"Morrowind", "BioShock", "Daxter", "The Darkness", "Half Life", "System Shock 2"};IEnumerable subset = from g in games where g.Length > 6 orderby g select g;foreach (string s in subset) Console.WriteLine("Item: {0}", s);Query ExpressionsLive Demo

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*41##LINQ Query Expressions (3)In LINQ a query is a basic language constructionJust like classes, methods and delegates in C#Query expressions are used to query and transform data from any LINQ-enabled data sourceA LINQ query is not executed untilYou iterate over the query resultsYou try to access any of the elements in the result set 42Query Operators and the LINQ Extension Methods Query operators in C# are keywords like:from, in, where, orderby, select, For each standard query operator a corresponding extension method existsE.g. where Where(IEnumerable)At compile time the C# compiler translates query expressions into expression treesExpression trees are sequences of method calls (from System.Linq.Enumerable)43Query Operators SyntaxThe basic syntax of LINQ queries is:

This selects all elements in games data sourceYou can apply criteria by the operator whereAny valid C# boolean expression can be used44IEnumerable subset = from g in games select g;IEnumerable subset = from g in games where g.Price < 20 select g;var subset = games.Select(g => g);var subset = games.Select(g => g). Where(g => g.Price < 20);Query Operators (2)Two sets of LINQstandard operatorsOperating on IEnumerableOperating on IQueryableLINQ query operators are shorthand versions for various extension methodsDefined in System.Linq.Enumerable typeExample:45IEnumerable subset = games.Where(g => g.Price < 20); var subset = from g in games where g.Price < 20 select g;Query Operators (3)The standard query operators provide query capabilities includingFiltering whereProjection select, selectManyAggregation Sum, Max, Count, AverageSorting orderbyGrouping groupby and many more46Standard Query Operators Example47string[] games = {"Morrowind", "BioShock","Half Life", "The Darkness","Daxter", "System Shock 2"};

// Build a query expression using extension methods// granted to the Array via the Enumerable type

var subset = games.Where(game => game.Length > 6). OrderBy(game => game).Select(game => game);

foreach (var game in subset) Console.WriteLine(game);Console.WriteLine();var subset = from g in games where g.Length > 6 orderby g select g;Standard Query OperatorsLive Demo

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*48##Query Expression Trees

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*49##Query Expression TreesA query expression tree is an efficient data structure representing a LINQ expressionType of abstract syntax tree used for storing parsed expressions from the source code Lambda expressions often translate into query expression treesIQueryable is interface implemented by query providers (e.g. LINQ to SQL, LINQ to XML, LINQ to Entities)IQueryable objects use expression trees50Query Expression Trees (2)LINQ queries can be performed over two standard .NET interfaces:IEnumerable At compile time IL is emittedIQueryable At compile time a query expression tree is emittedBoth are evaluated at runtime51Query Expression Trees (3)When any element of the IQueryable result is being accessed for the first timeA query is generated from the expression tree and is executed

52int[] nums = new int[] { 6, 2, 7, 1, 9, 3 };var numsLessThanFour = from i in nums where i < 4 select i;foreach (var item in numsLessThanFour) Console.WriteLine(item);Query is generated and executed hereVariable is of type IQueryableExpression Trees BenefitsIQueryable uses expression trees which provide it mechanisms:For smart decisions and optimizations when query is generatedBased on analysis of expression treesOptimizing multiple nested or complex queriesCombining multiple queries into very efficient single one53

LINQ to Objects

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*54##LINQ to ObjectsLINQ to Objects refers to using LINQ queries directly over IEnumerable collectionWithout the an intermediate LINQ provider or API, such as LINQ to SQL or LINQ to XMLApplicable to any enumerable collectionThe old school data retrieval approachWrite complex foreach loops that specify how to retrieve data from a collectionhe LINQ approach write declarative code that describes what to be retrieved55LINQ to Objects AdvantagesLINQ queries offer three main advantages over traditional foreach loopsThey are more concise and easy-to-readEspecially when filtering by multiple conditionsProvide powerful filtering, ordering, and grouping capabilitiesCan be ported to other data sources with little or no modification56LINQ to Objects ExampleLINQ to Objects is performing SQL-like queries on in-memory data collections and arrays57string[] presidents = { "Adams", "Arthur", "Buchanan", "Bush", "Carter","Cleveland","Clinton", "Coolidge", "Eisenhower", "Fillmore", "Ford", "Garfield","Grant", "Harding", "Harrison", "Hayes", "Hoover", "Jackson", "Jefferson", "Johnson", "Kennedy", "Lincoln", "Madison", "McKinley", "Monroe", "Nixon", "Pierce", "Polk", "Reagan", "Roosevelt", "Taft", "Taylor", "Truman", "Tyler", "Van Buren", "Washington", "Wilson"};string president = presidents.Where(p => p.StartsWith("Lin")).First();Console.WriteLine(president);string president = (from p in presidents where p.StartsWith("Lin") select p).First();LINQ to ObjectsLive Demo

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*58##Counting the Occurrences of a Word in a String Example59string text = "Historically, the world of data ";string searchTerm = "data";string[] source = text.Split( new char[] { '.', '?', '!', ' ', ';', ':', ',' }, StringSplitOptions.RemoveEmptyEntries);

// Use ToLower() to match both "data" and "Data"var matchQuery = from word in text where word.ToLower() == searchTerm.ToLower() select word;int wordCount = matchQuery.Count();int wordCount = text.Select( w => w.toLower() == searchTerm.ToLower()).Count();

Count the Occurrences of a Word in a StringLive Demo*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*60##Querying Collections

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*61##Querying CollectionsWhat can we query?Not everything can be queried by LINQ to ObjectsThe objects need to be a collectionIt must implement the IEnumerable interfaceThe good newsAlmost all standard collections in .NET Framework implements IEnumerable62Querying Collections (2)What can be queried using LINQ to Objects?Arrays T[]Generic lists ListGeneric dictionaries DictionaryStrings stringOther collections that implements IEnumerable63Querying ArraysAny kind of arrays can be used with LINQCan be even an untyped array of objectsQueries can be applied to arrays of custom objectsExample:64Book[] books = { new Book { Title="LINQ in Action" }, new Book { Title="LINQ for Fun" }, new Book { Title="Extreme LINQ" } };var titles = books .Where(book => book.Title.Contains("Action")) .Select(book => book.Title);var titles = from b in books where b.Title.Contains("Action") select b.Title;Querying Generic ListsThe previous example can be adapted to work with a generic listList, LinkedList, Queue, Stack, HashSet, etc.65List books = new List() { new Book { Title="LINQ in Action" }, new Book { Title="LINQ for Fun" }, new Book { Title="Extreme LINQ" } };var titles = books .Where(book => book.Title.Contains("Action")) .Select(book => book.Title);

Querying Generic ListsLive Demo*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*66##Querying StringsAlthough System.String may not be perceived as a collection at first sightIt actually is a collection, because it implements IEnumerableString objects can be queried with LINQ to Objects, like any other collection67var count = "Non-letter characters in this string: 8" .Where(c => !Char.IsLetter(c)) .Count();Console.WriteLine(count);// The result is: 8var count = (from c in "Non-letter" where !Char.IsLetter(c) select c).Count();LINQ Operations

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*68##Aggregation Operations An aggregation operation computes a single value from a collection of valuesExample of aggregation of field over a sequence of employees69

NameSalaryBay Ivan12500,00Bat Rambo13500,00Baba Yaga43300,00Kiro the King29800,00Bay Mangal25000,00......MAX(Salary)125500,00Aggregation MethodsAverage()Calculates the average value of a collectionCount()Counts the elements in a collectionMax()Determines the maximum value in a collectionSum()Sums the values in a collection70Aggregation Methods ExamplesCount()

Max()71double[] temperatures = {28.0, 19.5, 32.3, 33.6, 26.5, 29.7};int highTempCount = temperatures.Count(p => p > 30);Console.WriteLine(highTempCount);// The result is: 2double[] temperatures = {28.0, 19.5, 32.3, 33.6, 26.5, 29.7};double maxTemp = temperatures.Max();Console.WriteLine(maxTemp);// The result is: 33.6var highTemp = (from p in temperatures where p > 30 select p).Count();var highTemp = (from p in temperatures select p).Max();ProjectionsProjection refers to the act of transforming the elements of a collection into a different typeThe resulting type is dened by the developerProjection operators in LINQSelect projects single values that are based on a transform functionSelectMany projects collections of values into a new collection containing all values72Projections ExamplesSelect( w.Substring(0,1));Projections Examples (2)SelectMany()

74string[] sentence = new string[] { "The quick brown", "fox jumped over", "the lazy dog"};// SelectMany returns nine strings// (sub-iterates the Select result)IEnumerable allWords = sentence.SelectMany(segment => segment.Split(' '));foreach (var word in allWords) Console.Write(" {0}", word);// Result: The quick brown fox jumped over the lazy dogNo LINQ equvalentProjectionsLive Demo

LINQ*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*75##Conversions Converting a collection to a different typeCan change the type of the collectionCan change the type of the elementsConversion operations in LINQ queries are useful in a variety of applicationsFor example:Enumerable.AsEnumerableEnumerable.OfType Enumerable.ToArray(TSource) 76Conversion Methods If start with "As" Change the static type of the source collection but do not enumerate it If start with "To" Enumerate the source collection and turn each item into the corresponding collection type77string[] towns = {"Sofia", "Plovdiv", "Varna", "Bourgas", "Pleven"};IEnumerable strings = towns.AsEnumerable();List list = towns.ToList();SortingA sorting operation orders the elements of a sequence based on one or more attributesStandard query operatorOrderBy()OrderByDescending()ThenBy() performs a secondary sort in ascending orderThenByDescending()Reverse()78Sorting Example79string[] words = { "Bay Kolio", "Pinokio", "Dedo Mraz", "Baba Yaga", "Bay Mangal" };IEnumerable query = from word in words orderby word.Length, word.Substring(0, 1) descending select word;

foreach (string str in query) Console.WriteLine(str);/* The result is: Pinokio Dedo Mraz Bay Kolio Baba Yaga Bay Mangal*/var query = words.Select(word => word). OrderBy(word => word.Length). ThenByDescending( word => word.Substring(0, 1));GroupingOperation of putting data into groupsThe elements in each group share a common value for some attribute Example80

Creating Groups and MapsGroupBy()Groups elements that share a common attribute, called keyEach group is represented by a sequence of IGrouping(TKey,TElement) objectsToLookup()Inserts elements into a Lookup(TKey, TElement) based on a key selector functionDistinct()Returns distinct elements form a collection81Group By Examples82var people = new[] { new { Name = "Kiki", Town = "Plovdiv"}, new { Name = "Pepi", Town = "Sofia"}, new { Name = "Koko", Town = "Sofia"}, new { Name = "Mimi", Town = "Plovdiv"}};var peopleByTowns = from p in people group p by p.Town;foreach (var town in peopleByTowns){ Console.Write("Town {0}: ", town.Key); foreach (var person in town) Console.Write("{0} ", person.Name); Console.WriteLine();}var peopleByTowns = people.GroupBy(t => t.Town);Group By Examples (2)83int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

var numberGroups = from n in numbers group n by n % 3;

foreach (var g in numberGroups){ Console.Write("Remainder: {0} -> ", g.Key); foreach (var n in g) Console.Write("{0} ", n); Console.WriteLine();}// Remainder: 2 -> 5 8 2// Remainder: 1 -> 4 1 7// Remainder: 0 -> 3 9 6 0var numberGroups = numbers.GroupBy(n => n % 3);JoinsAction of relating or associating one data source object with a second data source objectThe two data source objects are associated through a common value or attribute84

Join MethodsJoinJoins two sequences based on key selector functionAnd extracts the joined pairs of valuesGroupJoinJoins two sequences based on key selector functionsAnd groups the resulting matches for each element85Joins Example86var owners = new[] { new { Name = "Koko", Town = "Plovdiv"}, new { Name = "Pepi", Town = "Sofia"},};var pets = new[] { new { Name = "Sharo", Owner = owners[0] }, new { Name = "Rex", Owner = owners[1] }, new { Name = "Poohy", Owner = owners[0] },};var petsWithOwners = from o in owners join p in pets on o.Name equals p.Owner.Name select new { Owner = o.Name, Pet = p.Name };foreach (var p in petsWithOwners) Console.WriteLine("{0} owned by {1}", p.Pet, p.Owner);var petsWithOwners = owners.Join(pets, (o => o.Name), (p => p.Owner.Name), (o, p) => new {o.Name, p.Name });

JoinsLive Demo

*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*87##Nested QueriesThe queries can be nestedFor example:Suppose we have collections of Person and collections of Role objectsWe want get all roles for given person (ID = 1)88var query = people .Where(p => p.ID == 1) .SelectMany(p => roles .Where(r => r.ID == p.RoleID) .Select(r => new { p.FirstName, p.LastName, r.Role }));

Nested QueriesLive Demo*(c) 2008 National Academy for Software Development - http://academy.devbg.org. All rights reserved. Unauthorized copying or re-distribution is strictly prohibited.*89##Questions???????????http://schoolacademy.telerik.comLanguage Integrated Query in .NET (LINQ)