Set Operators in LINQ

Set operators in LINQ are used to perform set function on sequences. There are four types of set operators in C#.

  • Concat
  • Union
  • Intersect
  • Except

Concat and Union

The Concat operator in LINQ is used to concatenate two sequences. On the other hand, the Union operator also concatenates the sequences but it removes duplicates from the two sequences. Have a look at the following example to see how Concat and Union work.

using System;
using System.Collections.Generic;
using System.Linq;

namespace CSharpTutorials {
    class Tutorial {
        static void Main()   {
            string[] sequence1 = { "Joseph", "Juana", "Sara", "Mike", "Angel", "Victoria" };
            string[] sequence2 = { "Joseph", "Merry", "Sara", "Halen", "Angel", "Elizabeth" };

            // Concatenating sequence1 and sequence2
            IEnumerable<string> output = sequence1.Concat(sequence2);

            // All the items from sequence1 and sequence2 will be displayed
            foreach (string s in output) Console.WriteLine(s);

            Console.WriteLine("=====================");
            // Taking union of sequence1 and sequence2
            output = sequence1.Union(sequence2);

            // All items from sequence1 and sequence2 will be displayed
            //Except duplicates
            foreach (string s in output)   Console.WriteLine(s);
            Console.ReadKey();
        }
    }
}

Download the code

Intersect and Except

The Intersect operator returns those items which are common in both the sequences. The Except operator returns all the items from the first sequence except those which also exit in the second sequence. Have a look at the example of Concat and Except operators.

using System;
using System.Collections.Generic;
using System.Linq;

namespace CSharpTutorials {
    class Tutorial {
        static void Main() {
            string[] sequence1 = { "Joseph", "Juana", "Sara", "Mike", "Angel", "Victoria" };
            string[] sequence2 = { "Joseph", "Merry", "Sara", "Halen", "Angel", "Elizabeth" };

            // Taking intersect of sequence1 and sequence
            IEnumerable<string> output = sequence1.Intersect(sequence2);

            // All the items common from sequence1 and sequence2 will be displayed
            foreach (string s in output)  Console.WriteLine(s);

            Console.WriteLine("=====================");
            // Taking Except of sequence1 and sequence2
            output = sequence1.Except(sequence2);

            // All items from sequence1 which are not in sequence2 will be displayed
            foreach (string s in output) Console.WriteLine(s);
            Console.ReadKey();
        }
    }
}

Download the code

Element Operators in LINQ

Element operators operate over a sequence and return only one element. There are four main types of element operators in LINQ. They are as follows

  • First
  • Last
  • Single
  • ElementAt

First and Last

The First operator returns the first element of the sequence while Last operator returns the last element. If lambda expression is passed to these operators they will return First and Last element that meets the condition specified by the lambda expression.

There are two variants of these operators as well: FirstOrDefault and LastOrDefault. The First and Last operators will through exception if no matching elements are found where as the FirstOrDefault and LastOrDefault methods will return the default values of the type if no matching element is found. Have a look at this example.

using System;
using System.Collections.Generic;
using System.Linq;

namespace CSharpTutorials {
    class Tutorial {
        static void Main() {
            string[] sequence1 = { "Joseph", "Juana", "Sara", "Mike", "Angel", "Victoria" };

            String output = sequence1.First();
            Console.WriteLine(output); // Joseph will be printed.

            // First element with K in it
            output = sequence1.First(e=>e.Contains("k"));
            Console.WriteLine(output); // Mike will be printed.

            output = sequence1.Last();
            Console.WriteLine(output); // Victoria will be printed

            // Last element with e in it
            output = sequence1.Last(e=>e.Contains("e"));
            Console.WriteLine(output); // Angel will be printed

            Console.ReadKey();
        }
    }
}

Download the code

Single & ElementAt

Single operator returns single value that matches the condition specified by the lambda expression. In case if no element matches the condition, the application throws error. To avoid an exception an alternate of Single operator SingleOrDefault can be used. Similarly, the ElementAt Operator returns the element at the specified index. Have a look at the following example.

using System;
using System.Collections.Generic;
using System.Linq;

namespace CSharpTutorials {
    class Tutorial {
        static void Main() {
            string[] sequence1 = { "Joseph", "Juana", "Sara", "Mike", "Angel", "Victoria" };

            String output = sequence1.Single(e=>e.Contains("l"));
            Console.WriteLine(output); // Angel will be printed.

            output = sequence1.ElementAt(2);
            Console.WriteLine(output); // Sara Value will be printed

            Console.ReadKey();
        }
    }
}

Download the code

Aggregate Methods in LINQ

The aggregate methods are used to perform aggregate operations such as sum, count, average, finding minimum and maximum values etc. Following are sum of the most commonly used aggregate operators in LINQ.

  • Count and LongCount
  • Min and Max
  • Sum and Average

Count and LongCount

The Count operators counts the total number of items in the sequence. If a predicate is passed to it, it will count the total number of elements that match that predicate. LongCount also performs the same operation but it returns a 64 bit integer which can be used to store values greater than 2 billion.

Min and Max

Min and Max operators find the minimum and maximum value in the sequence respectively. If a predicate is passed to it, it will find the minimum and maximum value that match that predicate.

Sum and Average

Sum and Average operators calculate the sum and average of values in the sequence, respectively. If a predicate is passed to it, it will calculate the sum and average of values in the sequence that match that predicate.

Have a look at the following example to see the working of these functions.

using System;
using System.Collections.Generic;
using System.Linq;

namespace CSharpTutorials {
    class Tutorial {
        static void Main() {
            string[] sequence1 = { "Joseph", "Juana", "Sara", "Mike", "Angel", "Victoria" };

            int total = sequence1.Count();
            Console.WriteLine(total); // 6 will be printed.

            total = sequence1.Count(v=>v.Contains("e"));
            Console.WriteLine(total); // 3 will be printed.

            int[] randomnums = { 12, 43, 53, 23, 67, 54, 101, 54, 83 };

            total = randomnums.Max();
            Console.WriteLine(total); // 101 will be printed.

            total = randomnums.Min();
            Console.WriteLine(total); // 12 will be printed.

            double val = randomnums.Average();
            Console.WriteLine(val); // average of items will be printed

            total = randomnums.Sum();
            Console.WriteLine(total); // sum of items will be printed

            Console.ReadKey();
        }
    }
}

Download the code

LINQ Projection Operators

There are two types of Projection operators in LINQ: Select and SelectMany.

Select Operator

The projection operators take an input sequence, performs some projection on the sequence and returns the sequence. The number of items in the input sequence remain same after projection, unless or until some lambda expression is used which filters records. Have a look at the following example to see how Select operator works.

using System;
using System.Collections.Generic;
using System.Linq;

namespace CSharpTutorials {
    class Tutorial {
        static void Main() {
            // An array sequence with some items
            int[] randomnums = { 1, 12, 45, 32, 65, 23, 57, 23, 45, 12, 34, 90, 27, 48, 10 };

            // Select query to double the num values.
            IEnumerable<int> doublenums = randomnums.Select(n => n * 2);
            foreach (int val in doublenums) Console.Write(val+" ");
            Console.WriteLine("");
            //Performing indexed Projection
            IEnumerable<int> indexednums = randomnums.Select((j,k) => j *k);
            foreach (int val in indexednums) Console.WriteLine(val);
            Console.WriteLine("");
            Console.ReadKey();
        }
    }
}

Download the code

In above code, a collection of some random numbers have been created. Next Select operator is applied on this operator and returns a collection where each item is twice of its original value. This means that the numbers of items remain some, however they have been doubled. Also, In above example, Indexed projection is used where each item is multiplied with its own index number and the resultant sequence is returned.

SelectMany Operator

SelectMany query is used to join multiple sub-sequences into one and returns the resultant sequence as a flat single sequence.

using System;
using System.Collections.Generic;
using System.Linq;

namespace CSharpTutorials {
    class Tutorial {
        static void Main() {
            string[] cararray = { "Ford", "BMW", "Honda", "Toyota", "Suzuki" };

            // Here each car name will be converted to character array
            // Then all these character arrays will be merged into a collection
            // of characters via SelectManny
            IEnumerable<char> charsinallchar = cararray.SelectMany(c => c.ToCharArray());
            foreach ( char c in charsinallchar) Console.Write(c+"|");
            Console.ReadKey();
        }
    }
}

Download the code

In the above code, a string type array carrarray has been defined which contain names of some cars. Here the SelectMany query converts all these items in the cararray into individual character arrays via To.CharArray() and then all of these sequences are merged into one sequence of characters.

Ordering in LINQ

There are four operators that are used for ordering output sequence in linq. They are as follows:

  • OrderBy
  • ThenBy
  • OrderByDescending
  • ThenByDescending

Orderby and ThenBy

The OrderBy operator is used to sort the data in the ascending order according to the condition specified by the lambda expression. The ThenBy operator is used to further sort those items that equal in the sorted order specified by the previous OrderBy operator. OrderBy and ThenBy operators are used in conjunction with each other. Have a look at the following example.

using System;
using System.Collections.Generic;
using System.Linq;

namespace CSharpTutorials {
    class Tutorial {
        static void Main() {
            string[] cararray = { "BMW", "Ford", "Toyota", "Honda", "Mercedez", "Capri" };
            IEnumerable<string> sortedcars = cararray.OrderBy(c => c.Length).ThenBy(s=>s);

            foreach (string s in sortedcars)  Console.WriteLine(s);
            Console.ReadKey();
        }
    }
}

Download the code

In the above code, a collection named cararray has been defined which contains names of different car companies. This collection is sorted by OrderBy operator according to length. This will sort the items according to the ascending order of their length. However, Honda and Capri have equal length i.e. 5. In such cases the item that comes first in the collection is printed first. However to print Capri first, i.e in the alphabetical order, the ThenBy operator is used and the lambda expression defines that sort the item alphabetically. In this case Capri shall be added before Honda.

OrderbyDescending and ThenByDescending

These operators are similar to OrderBy and ThenBy operators except they sort the items in the sequence in descending order. Have a look at their working example.

using System;
using System.Collections.Generic;
using System.Linq;

namespace CSharpTutorials {
    class Tutorial {
        static void Main() {
            string[] cararray = { "BMW", "Ford", "Toyota", "Honda", "Mercedez", "Capri" };
            IEnumerable<string> sortedcars = cararray.OrderByDescending(c => c.Length).ThenByDescending(s=>s);

            foreach (string s in sortedcars)   Console.WriteLine(s);
            Console.ReadKey();
        }
    }
}

Download the code

Joining in LINQ

Joining in LINQ is similar to using JOIN operators in LINQ. There are two types of operator that perform JOIN functions in LINQ: Join and GroupJoin operators. These operators are used to combine two input sequence based on a certain condition and return the output as one sequence. The Join operator returns the sequence in the flat form while GroupJoin returns the sequence in hierarchical form.

Join Operator

Have a look at the example of Join operators.

using System;
using System.Collections.Generic;
using System.Linq;

namespace CSharpTutorials {

    public class Customer {
        public int custId;
        public string custname;

        public Customer(int cid, string cname) {
            this.custId = cid;
            this.custname = cname;
        }
    }

    public class Order {
        public int custId;
        public string itemname;

        public Order(int cid, string iname) {
            this.custId = cid;
            this.itemname = iname;
        }
    }

    class Tutorial {
        static void Main() {
            List<Customer> customercollection = new List<Customer>();

            Customer c1 = new Customer(2, "John");
            Customer c2 = new Customer(3, "Mike");
            Customer c3 = new Customer(4, "Sara");
            Customer c4 = new Customer(5, "Kelly");
            Customer c5 = new Customer(6, "Elizabeth");

            customercollection.Add(c1);
            customercollection.Add(c2);
            customercollection.Add(c3);
            customercollection.Add(c4);
            customercollection.Add(c5);

            List<Order> ordercollection = new List<Order>();
            Order o1 = new Order(2, "Laptop");
            Order o2 = new Order(2, "LCD");
            Order o3 = new Order(4, "Furniture");
            Order o4 = new Order(6, "Headseat");
            Order o5 = new Order(6, "Standing Mic");

            ordercollection.Add(o1);
            ordercollection.Add(o2);
            ordercollection.Add(o3);
            ordercollection.Add(o4);
            ordercollection.Add(o5);

            IEnumerable<string> reports = from c in customercollection
                                          join o in ordercollection
                                          on c.custId equals o.custId
                                          select c.custname + " purchased " + o.itemname;
            foreach (string repline in reports) Console.WriteLine(repline);
            Console.ReadKey();
        }
    }
}

Download the code

In the above code, collection of two classes Customer and Order have been created. Both the classes have a custId field. This is the field on which the Join will be applied and the name of the Customer and Item will be returned as a single sequence. This is similar to full Join in SQL

GroupJoin

GroupJoin returns joined query in hierarchical form, which means that the customer name will be displayed first, followed by all his purchases and then the next customer name will be displayed. The GroupJoin query is similar to Join query, except into operator is used before Select. Have a look at the following example.

using System;
using System.Collections.Generic;
using System.Linq;

namespace CSharpTutorials {

    public class Customer {
        public int custId;
        public string custname;

        public Customer(int cid, string cname) {
            this.custId = cid;
            this.custname = cname;
        }
    }

    public class Order {
        public int custId;
        public string itemname;

        public Order(int cid, string iname) {
            this.custId = cid;
            this.itemname = iname;
        }
    }

    class Tutorial {
        static void Main() {
            List<Customer> customercollection = new List<Customer>();

            Customer c1 = new Customer(2, "John");
            Customer c2 = new Customer(3, "Mike");
            Customer c3 = new Customer(4, "Sara");
            Customer c4 = new Customer(5, "Kelly");
            Customer c5 = new Customer(6, "Elizabeth");

            customercollection.Add(c1);
            customercollection.Add(c2);
            customercollection.Add(c3);
            customercollection.Add(c4);
            customercollection.Add(c5);

            List<Order> ordercollection = new List<Order>();
            Order o1 = new Order(2, "Laptop");
            Order o2 = new Order(2, "LCD");
            Order o3 = new Order(4, "Furniture");
            Order o4 = new Order(6, "Headseat");
            Order o5 = new Order(6, "Standing Mic");

            ordercollection.Add(o1);
            ordercollection.Add(o2);
            ordercollection.Add(o3);
            ordercollection.Add(o4);
            ordercollection.Add(o5);

            var reports = from c in customercollection
                                          join o in ordercollection
                                          on c.custId equals o.custId
                                          into customerpurchases
                                          select new { CustomerName = c.custname, customerpurchases };
            foreach (var custname in reports) {
                if (custname.customerpurchases.Count() > 0) {
                    Console.WriteLine(custname.CustomerName + " purchased ");
                    foreach (var item in custname.customerpurchases) {
                        Console.WriteLine(item.itemname);

                    }
                }
            }
            Console.ReadKey();
        }
    }
}

Download the code

Introduction to LINQ

LINQ stands for language integrated query. LINQ is a .NET alternative to SQL. LINQ is designed for those .NET developers who don’t find themselves comfortable with SQL. A LINQ query operates over some data. This data consists of two parts: A sequence that must implement the IEnumerable interface and some items. For instance an array is a collection that implements IEnumerable interface and contains some item. Consider the following code.

  // An array sequence with some items
            string[] cars = { "Toyota", "Ford", "BMW", "Honda" };

In the above code, the array “cars” is a sequence while string type elements “Toyota”, “Ford” etc are the items.

Linq contains query operators that are basically static extension method of the Enumerable class of the System.Linq namespace. There are around 40 query operators in this class. A query operator is used to act on a LINQ data sequence and produce another sequence. The cars sequence is a local sequence i.e. this sequence exits in the memory of the computer. The LINQ queries that operate on local type of sequence are called local queries. LINQ queries can also operate on remote data such as SQL databases and XML files.

A query expression in LINQ consists of an operator and a sequence on which the operator acts and yield some results. A simplest query expression consists of one sequence and one query operator. Have a look at the following example to see how we can retrieve name of all the cars that doesn’t contain letter ‘o’ in their names.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace CSharpTutorials {
    class Tutorial {
        static void Main() {
            // An array sequence with some items
            string[] cars = { "Toyota", "Ford", "BMW", "Honda" };

            // Linq query to find cars with no letter o in it
            IEnumerable<string> cars2 = cars.Where(c => !c.Contains("o"));
            foreach (string c in cars2) Console.WriteLine(c);
            Console.ReadKey();
        }
    }
}

Download the code

In the above code, “where” query operator is being used to check whether the item in the cars array contains the letter ‘o’ in it or not. If the item doesnt contain o, it is added in the output sequence, else it is filtered. Once the operator has iterated over each item, the output sequence is returned. In cars array, only “BMW” was the item which did not contain ‘o’, therefore this item will be returned and displayed on the output.

Grouping Data via GroupBy in LINQ

Suppose, a there is a collection of student record where name of each student, the name of the course and the marks they have taken against each course is stored. You want to get total marks of the student in all course, how would you do this? this is where GroupBy clause is handy. It groups the data on the basis of the specified attribute. Have a look at the following example to understand this concept.

using System;
using System.Collections.Generic;
using System.Linq;

namespace CSharpTutorials {

    public class StudentRecord {

        public string studname;
        public string coursename;
        public int marks;

        public StudentRecord(string sn, string sc, int sm) {
            this.studname = sn;
            this.coursename = sc;
            this.marks = sm;
        }
    }

    class Tutorial {
        static void Main() {
            StudentRecord sr = new StudentRecord("Mike", "Mathematics", 89);
            StudentRecord sr1 = new StudentRecord("John", "Mathematics", 45);
            StudentRecord sr2 = new StudentRecord("Sara", "Mathematics", 67);
            StudentRecord sr3 = new StudentRecord("Will", "Mathematics", 60);
            StudentRecord sr4 = new StudentRecord("Mike", "English", 91);
            StudentRecord sr5 = new StudentRecord("Sara", "English", 78);
            StudentRecord sr6 = new StudentRecord("Mike", "Science", 71);
            StudentRecord sr7 = new StudentRecord("Sara", "Science", 94);
            StudentRecord sr8 = new StudentRecord("John", "English", 78);

            List<StudentRecord> studentlist =new List<StudentRecord>();

            studentlist.Add(sr);
            studentlist.Add(sr1);
            studentlist.Add(sr2);
            studentlist.Add(sr3);
            studentlist.Add(sr4);
            studentlist.Add(sr5);
            studentlist.Add(sr6);
            studentlist.Add(sr7);
            studentlist.Add(sr8);

            var totalmarks = studentlist.GroupBy(n => n.studname).Select(g => new  {
					Name = g.Key,
					MarksTotal = g.Sum(x => x.marks)
				});

            foreach (var studentrec in totalmarks) Console.WriteLine(studentrec.Name + ":" + studentrec.MarksTotal);

            Console.ReadKey();
        }
    }
}

Download the code

The above code groups all the students by their names and then uses aggregate Sum function to calculate sum of marks in all of the courses that they have take. In the output you shall names of the students along with their total obtained marks.

LINQ Fluent vs Query Syntax

There are two ways to create Linq queries: One is via fluent syntax which is modern, more robust and fast approach to creating Linq queries and the other is query syntax which follows SQL-like structure to write LINQ queries. Lets have a look at the examples of both of them.

Fluent Syntax

Fluent syntax uses lambda expressions as a parameter for the query operators. Using query syntax, we can easily chain multiple queries operator together to form a more complex query. Have a look at the following example.

using System;
using System.Collections.Generic;
using System.Linq;

namespace CSharpTutorials {
    class Tutorial {
        static void Main() {
            // An array sequence with some items
            string[] cars = { "Toyota", "Ford", "BMW", "Honda", "Mercedes","Suzuki" };

            // Linq query to find cars with no letter o in it
            IEnumerable<string> cars2 = cars.Where(c => !c.Contains("a")).OrderBy(t=>t.Length).Select(y=>y.ToUpper());
            foreach (string c in cars2)  Console.WriteLine(c);
            Console.ReadKey();
        }
    }
}

Download the code

In the above code, three Linq operators Where, OrderBy and Select has been chained together to form a complex query. This query will first filter all the car names which doesn’t contain a letter ‘a’ in them using Where operator. Then the OrderBy operator sorts the car names in the increase order of the name of the length and finally Select operator capitalizes the names of the car and return the sequence.

Query Expression

Like fluent syntax, you can also use query expression to write linq queries. Query expression is similar to SQL queries. Let us see how we can write the query in query expression that we wrote in fluent syntax in last example.

using System;
using System.Collections.Generic;
using System.Linq;

namespace CSharpTutorials {
    class Tutorial {
        static void Main() {
            // An array sequence with some items
            string[] cars = { "Toyota", "Ford", "BMW", "Honda", "Mercedez","Suzuki" };

            // Linq query to find cars with no letter o in it
            IEnumerable<string> cars2 = from c in cars
                                        where !c.Contains("a")
                                        orderby c.Length
                                        select c.ToUpper();
            foreach (string c in cars2) Console.WriteLine(c);
            Console.ReadKey();
        }
    }
}

Download the code

In the above example again the Where, Orderby and Select operators are being used in conjunction but you can see here that this syntax is more similar to SQL statements. An important point to keep in mind here is that a query in Query expression always starts with a From clause and ends with Select or GroupBy clause.

Linq Filtering Operators in C#

Filtering operators are the static extension methods in the IEnumerable class that are used to filter data from a sequence. There are four most commonly used filtering operators in C#:

  • Where
  • Take and Skip
  • TakeWhile and SkipWhile
  • Distinct

Where

The where operator is used to filter the sequence based on some condition which is passed in the form of lambda expression to it in case of fluent syntax and in the form of simple expression in case of Query expression.

Take And Skip

The Take function is used to retrieve the first n elements and discard the rest while Skip function is used to discard the first n elements and retrieve the rest.

TakeWhile & SkipWhile

The TakeWhile operators keeps on retrieving the items from the sequence until a certain condition becomes false. Similarly, SkipWhile keeps on discarding the items in the sequence until a certain condition becomes false and then retrieves the rest.

Distinct

The distinct function is used to retrieve the distinct records from the sequence. All the duplicates are ignored.

The following example demonstrates functionality of all of these filters.

using System;
using System.Collections.Generic;
using System.Linq;

namespace CSharpTutorials {
    class Tutorial {
        static void Main() {
            // An array sequence with some items
            int[] randomnums = { 1, 12, 45, 32, 65, 23, 57, 23, 45, 12, 34, 90, 27, 48, 10 };

            // retrieving numbers between 20 and 60
            IEnumerable<int> wherefilter = randomnums.Where(n => n > 20 && n < 60);
            foreach (int n in wherefilter) Console.Write(n+" ");

            //retrieving first 10 numbers
            IEnumerable<int> takefilter = randomnums.Take(10);
            Console.WriteLine("");
            foreach (int n in takefilter) Console.Write(n + " ");

            //skipping first 10 and leaving rest
            Console.WriteLine("");
            IEnumerable<int> skipfilter = randomnums.Skip(10);
            foreach (int n in skipfilter) Console.Write(n + " ");

            //taking while
            Console.WriteLine("");
            IEnumerable<int> takewhilefilter = randomnums.TakeWhile(n=>n<60);
            foreach (int n in takewhilefilter) Console.Write(n + " ");

            //skipping while
            Console.WriteLine("");
            IEnumerable<int> skipwhilefilter = randomnums.SkipWhile(n => n < 60);
            foreach (int n in skipwhilefilter) Console.Write(n + " ");

            //getting distinct
            Console.WriteLine("");
            IEnumerable<int> disticntfilter = randomnums.Distinct();
            foreach (int n in disticntfilter) Console.Write(n + " ");            

            Console.ReadKey();
        }
    }
}

Download the code

Copyright 2005-2016 KnowledgeHills. Privacy Policy. Contact .