Language INtegrated Query or LINQ for short , is a very powerful feature in C# , which can be used to retrieve and query various kinds of collections and data sources.
Traditionally , queries against data is mostly done through strings without type checking at compile time or IntelliSense support , which makes it difficult to write queries especially large queries that involve various conditions within a single query, additionally , you need to learn a different query language for the various data sources , like SQL databases and XML documents , which is somewhat cumbersome.
So fortunately, LINQ comes for the rescue.
LINQ provides a couple of ways to write queries
1: Query expressions which are written in a declarative query syntax similar to SQL .
2: Extension methods with Lambda expressions.
And to explain the variety of features LINQ provides , we will use examples using both the query expressions syntax and extension methods.
For that purpose , we will use a simple console application for the sake of simplicity , but keep in mind that all the examples mentioned below are viable and applicable in all use cases no matter what the project type is.
Ok , so create a C# console app , and make sure to use top-level statements so your codes looks a bit cleaner without all the boilerplate code.
Let's declare a basic array of integers first...
int[] numbersArray = {2 , -1 , 10 , 99 , 78 , -21 , 45 , 0 , -120};
Ok , this simple array will be our data source for now.
We will write a simple query to get all the negative numbers , the implementation goes as follows
var negativeNumbers = from number in numbersArray
where number < 0
select number;
We can use the var keyword to let the compiler infer the type of this variable , which is called a query variable in this case , this variable actually stores the query and not the collection of the negative numbers , the query will be converted only when executed , so , we will use a foreach loop for that
foreach(int number in negativeNumbers)
{
Console.Write($"{number} ");
//OUTPUT : -1 , -21 , -120
}
This way , we used the query expression syntax , let's see how we can do it with the extension methods way
var negativeNumbers = numbersArray.Where(x => x < 0);
This one line basically does the same thing as the previous query , this line reads like this : from the numbers array , select all the numbers that are less than 0 .
Let's try something new , we will now get both the first and last elements in the array , we'll do it with the extension methods cause it's pretty easy.
//2
int first = numbersArray.First();
//-120
int last = numbersArray.Last();
If you are using Visual Studio , you might notice things like FirstOrDefault() & LastOrDefault() , these are similar to First() & Last() except , when an element is not found in the sequence , they return the default value , 0 for value types and null for reference types.
Ok , now we'll check if a data source is empty or not , to do that , again , it's fairly simple , all we gotta do is call the Any() extension method on the data source , if it's empty , it'll return false , if not , then it'll return true.
bool anythingThere = numbersArray.Any();
//OUTPUT: true
Our data source has values in it , so this line will return true.
Now , we will ramp up the game a bit , we will declare an employee class , and then initialize a generic list with some dummy values as our data source.
Create a new class named Employee
public class Employee
{
public string FirstName {get; set;}
public string LastName {get; set;}
public decimal Salary {get; set;}
}
This should do , we are trying to keep it as simple as possible here.
I'll create a List of the Employee type we just introduced and use some dummy names and values just for the purpose of our queries.
List<Employee> employees = new()
{
new Employee {FirstName = "Tony" , LastName = "Dude" , Salary = 100_000 },
new Employee {FirstName = "Bro" , LastName = "Space" , Salary = 80_000},
new Employee {FirstName = "Jeff" , LastName = "Stanley" , Salary = 122_020},
new Employee {FirstName = "Rick" , LastName = "Stark" , Salary = 12_099},
new Employee {FirstName = "Alex" , LastName = "Peters" , Salary = 7_400},
new Employee {FirstName = "Tracey" , LastName = "Peters" , Salary = 217_400}
};
I Truly apologize for the horrible names , but they'll do for now.
With that out of the way , let's query the new data source to get the first names that contain the letter O.
Query Expressions
var containsO = from employee in employees
where employee.FirstName.ToLower().Contains('o')
select employee;
//OUPUT : TONY , BRO
The cool thing about query expressions is that they read almost like normal english , so query reads like this :
for each employee in the employees collection , select all employees whose first name contains the letter o after converting the first name to lower case.
Ok , we've talked enough about retrieving data and stuff , how about some math operations that LINQ provides for us , let's apply some of them now.
Finding the SUM of all the employees' salaries , let's code it
decimal salariesSum = employees.Sum(e => e.Salary); //OUTPUT : 538919
This one line calculates the sum of all the salaries , and it returns a decimal cause the Salary property is of type decimal which makes perfect sense.
Finding the AVERAGE of the salaries of our imaginary employees , again , with LINQ , it's pretty simple , let's see it in action
decimal averageSalary = employees.Average(e => e.Salary); //OUTPUT : 89819.833....
Finding the MAXIMUM salary in our collection
decimal max = employees.Max(e => e.Salary); //OUTPUT : 217400
Finding the MINIMUM salary in our collection , similar to the maximum , we just replace Max() with Min()
decimal min = employees.Min(e => e.Salary);
OK !
We've covered some of the basic things that LINQ can provide for you as a C# developer , as you can tell , there are plenty of productive functionality that LINQ brings to the table , and just for reference , we applied these functions on basic data sources like an array of numbers and a basic generic list , but LINQ works with all sorts of data sources , like the DB SETS in Entity Framework Core so you can query data from your database tables effectively through LINQ.
Finally , a small explanation of how a query expression is structured
A query expression always MUST start with the keyword from x in data source , then we can stack up some conditions , and then the final line MUST end with select or group.
I hope you found that useful and was worth your time , but obviously , there's still so much to learn in LINQ beyond the basics of today , so if you wanna continue digging deeper in LINQ , make sure to check out Microsoft Docs for extra help and to further deepen your knowledge of the technology.
Thanks For Reading ! :)
Top comments (0)