Language Integrated Query (LINQ) is a query capability which is integrated in programming languages. The most popular .NET programming languages C# and VB has this capability. LINQ is an abstraction by which we can query heterogeneous data sources with the same syntax. Though LINQ has some small difference depending on the provider. For example not all features supported in LINQ to Entity or LINQ to SQL. Though it is an declarative syntax and easy to learn. LINQ comes in some predefined flavor.
- LINQ to Objects
- LINQ to DataSet
- LINQ to XML
- LINQ to SQL
- LINQ to Entity
Also LINQ is extensible means we can use any third party provider with LINQ. For example we can use any third party provider to query data from facebook using LINQ.
LINQ has the SQL like syntax. The programmer who is familiar with SQL syntax has a easy time with LINQ syntax. No means what type of LINQ you are using the basic syntax and the pattern will same. LINQ can be work on any collection which implements IEnumerable(of T). It has from clause to start the query. There is range variable in which it store the data from the collection. There are other clauses like where to filter result, order by to sort result set, select to return result. The basic syntax of LINQ is follows.
string[] names = new string[] { "rahul", "mita", "bob", "rohit" }; // 'names' is the collection. // 'name' is the range variable. IEnumerable<string> query = from name in names select name; foreach (string item in query) { Console.WriteLine(item); }
Syntax for where clause
IEnumerable<string> query = from name in names where name.StartsWith("r") select name;
Many LINQ query finish with select clause. We can also project the result.
class Student { public string Name { get; set; } public string Subject { get; set; } public byte Age { get; set; } } class Program { public void Main() { IEnumerable<Student> students = new List<Student>() { new Student() { Name = "rahul", Subject = ".NET", Age = 25 }, new Student() { Name = "mita", Subject = "HTML", Age = 22 }, new Student() { Name = "bob", Subject = "C#", Age = 30 }, new Student() { Name = "rohit", Subject = "Java", Age = 27 } }; // Anonymous type. var query = from student in students where student.Age >= 25 select new { student.Name, student.Subject }; foreach (var item in query) { Console.WriteLine(item.Name + " " + item.Subject); } } }
Here we do not want all the properties of Student. We only want the Name and the Subject. So here we create a new anonymous type (a type which creates on the fly, which has no name). Notice the var keyword in the return type. But if we want to use the new type for example for type casting then we have to create a new type for that.
class TempStudent { public string Name { get; set; } public string Subject { get; set; } } class Program { public void Main() { IEnumerable<TempStudent> query = from student in students where student.Age >= 25 select new TempStudent { Name = student.Name, Subject = student.Subject }; foreach (TempStudent item in query) { Console.WriteLine(item.Name + " " + item.Subject); } } }
LINQ use deferred execution. That means the actual result will not retrieve until when the query is executing in for each loop in this case. If we want to perform the actual result retrieval in place (not deferred execution) then we have to use one of the extension method.
IEnumerable<TempStudent> query = (from student in students where student.Age >= 25 select new TempStudent { Name = student.Name, Subject = student.Subject }).ToList(); // Extension method.
We can use join just like we can do in SQL.
class Faculty { public int Id { get; set; } public string Name { get; set; } } class Student { public int Id { get; set; } public string Name { get; set; } public int FacultyId { get; set; } } class Program { static void Main(string[] args) { IEnumerable<Faculty> facs = new List<Faculty>() { new Faculty() { Id = 1, Name = "fac 1" }, new Faculty() { Id = 2, Name = "fac 2" }, new Faculty() { Id = 3, Name = "fac 3" }, new Faculty() { Id = 4, Name = "fac 4" }, }; IEnumerable<Student> stus = new List<Student>() { new Student() { Id = 1, Name = "st 1", FacultyId = 1 }, new Student() { Id = 2, Name = "st 2", FacultyId = 3 }, new Student() { Id = 3, Name = "st 3", FacultyId = 1 }, new Student() { Id = 4, Name = "st 4", FacultyId = 2 }, }; var facQuery = from f in facs join s in stus on f.Id equals s.FacultyId select new { FacName = f.Name, StudentName = s.Name }; foreach (var item in facQuery) { Console.WriteLine(item.FacName + " " + item.StudentName); } } }
We can also do left outer join in LINQ. But this concept is not same with SQL counterpart.
var facQuery = from f in facs join s in stus on f.Id equals s.FacultyId into Students from s in Students.DefaultIfEmpty() // Preserves left-hand elements that have no matches on the right side. select new { FacName = f.Name, StudentName = (s != null) ? s.Name : "(no students)" };
For more information please take a look at 101 LINQ Samples.