LINQ (Language Integrated Query)

C sharpLinq is a component of .NET Framework that is used to send queries. We have C# extension methods that allow us to filter, select, sort data. Linq is strongly typed and allows us to query different data sources as long as a provider has obviously been written.

Linq

Linq offers a number of extension methods such as Select, Where, Order by that allow us to query lists. We can pass a lambda expression as an argument to many of these extension methods. A list is any class that implements the IEnumerable interface. If a class implements such an interface then we can iterate through it with a foreach loop. The classes that implement IEnumerable strive to provide us with three essential functionality:

  • To access sequentially, that is, to scroll forward the list.
  • Read the current element.
  • Start over.

Let’s first try to clarify with a code example what extension methods are.

THE EXTENSION METHOD

using System;
using System.Linq;
namespace Linq
{
    public class Program
    {
        static void Main(string[] args)
        {
          Azienda a = new Azienda{Denominazione="Mario Rossi",RagioneSociale="S.P.A."};
          Console.WriteLine(a.FullName());
        }
    }
    public class Azienda
    {
        private string denominazione;
        private string ragioneSociale;
        public string Denominazione
        {
            get => denominazione;
            set => denominazione=value;
        }
        public string RagioneSociale
        {
            get => ragioneSociale;
            set => ragioneSociale=value;
        }
    }
    public static class ExtensionAzienda
    {
        public static string FullName(this Azienda str)=>$"{str.Denominazione} {str.RagioneSociale}";
    }
}

Extension methods allow you to “add” methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are static methods, but they are called as if they were instance methods on the type In the example to create an extension method on the company class you need to define a static method inside a static class and use the keyword this before the type . The Where extension method takes care of filtering a list of elements, that is, of producing a new list containing a variable number of elements, from 0 to all, based on our logic that we will pass to it with a lambda expression. LINQ has several extension methods. Here are just a few:

  • Where produces a new list containing only the elements that comply with our filter criteria;
  • Select projects the elements, that is, it produces a new list whose elements are of another type;
  • Sum, Count, Average produce a scalar value by adding, counting or averaging the items in the list.
Extension Method
Linq operators

ENTITY FRAMEWORK NOTES

Linq is the basis of Microsoft’s Entity Framework Core, which allows you to move from the relational world of databases to entity classes. An ORM (Object Relational Mapper) is a technology that allows access to data located in relational databases. Data can be retrieved with strongly typed queries, rather than SQL queries which are prone to making us make typing mistakes. The ORM takes care of “translating” our strongly typed queries into SQL. Furthermore, it reads the results found by the database and returns them to us in the form of objects (or graphs of objects) thanks to a phase called materialization. An ORM is therefore a layer of abstraction that tends to obviate the rigidity of the relational world and allows us to exploit all the expressiveness of a language like C#. On the other hand, an ORM has a performance cost precisely because it has to perform mapping logic to “adapt” the peculiarities of the relational world to those of the object world.

using System;
using System.Linq;
using System.Collections.Generic;
namespace Linq
{
    public class Program
    {
        static void Main(string[] args)
        {
           List<Persona> persone = new List<Persona>() {
               new Persona {Nome="Mario",Cognome="Bianchi",Eta=55,Altezza=170,Peso=80},
               new Persona {Nome="Mario",Cognome="Rossi",Eta=40,Altezza=160,Peso=80},
               new Persona {Nome="Mario",Cognome="Rossi",Eta=40,Altezza=178,Peso=85},
               new Persona {Nome="Franco",Cognome="Rossi",Eta=60,Altezza=180,Peso=70},
               new Persona {Nome="Susanna",Cognome="Verdi",Eta=25,Altezza=170,Peso=60},
               new Persona {Nome="Luigi",Cognome="Bianchi",Eta=55,Altezza=175,Peso=90}
            };
            Func<Persona, bool> myFunc = (Persona p) => p.Nome =="Mario";
            IEnumerable<Persona> pers = persone.Where(myFunc); //We have provided the predicate that the intellisense suggests.
                                                               //actually the lambda can be given as an argument
                                                               //of Where. We have specified that we want to filter all of them
                                                               //the people whose Name is Mario.
            foreach(var item in pers)
              Console.WriteLine(item.Denominazione());
            /*- Now we want to select all the people whose surname is Rossi,
             we select the age and add it up. */
            int sum = persone.Where(z=>z.Cognome=="Rossi")
                                .Select(z=>z.Eta)
                                .Sum();//Instead of Sum () we can use the rest of the
                                       //aggregation operators
            Console.WriteLine(sum);  
           //We add Distinct() if there are duplicate values it takes only one
             int somma = persone.Where(z=>z.Cognome=="Rossi")
                                .Select(z=>z.Eta)
                                .Distinct()
                                .Sum();
            Console.WriteLine(somma);          
            try
            {         
                //Extraction of individual First and Last objects              
                Persona p = persone.Where(z=>z.Cognome=="Rossi")
                                    .First();//First Extension Method throws an exception
                                             //if it doesn't find values like FirstOrDefault ().
                Console.WriteLine(p.Denominazione()); 
            }  
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
            } 
            try
            {                          
                Persona p = persone.Where(z=>z.Cognome=="Verdi")
                                    .Single(); //Single () returns only one value
                                               //throw an exception
                                               //if it finds duplicate lines.
                Console.WriteLine(p.Denominazione()); 
            }  
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
            } 
            try
            {         
               //OrderBy.                  
                IEnumerable<Persona> p = persone.Where(z=>z.Cognome=="Rossi")
                                                .OrderBy(x=>x.Peso);
                                                 
                                               
                foreach (var item in p)
                    Console.WriteLine(item.Denominazione());             
                
            }  
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
            } 
            try
            {         
               //Raggruppare               
                var p = persone.GroupBy(p=>p.Cognome);;
                foreach(var item in p)
                {
                    foreach(var s in item)
                    {
                        Console.WriteLine(s.Denominazione());
                    }
                }                             
                                                 
            }  
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
            } 

        }
    }
    public class Persona
    {
        private string nome;
        private string cognome;
        private int eta;
        private int altezza;
        private int peso;
        public string Nome
        {
            get => nome;
            set => nome=value;
        }
        public string Cognome
        {
            get => cognome;
            set => cognome=value;
        }
         public int Eta
        {
            get => eta;
            set => eta=value;
        }
        public int Altezza
        {
            get => altezza;
            set => altezza=value;
        }
        public int Peso
        {
            get => peso;
            set => peso=value;
        }
    }
    public static class Extension
    {
        public static string Denominazione(this Persona value)
             =>$"{value.Nome} {value.Cognome} {value.Eta}";
    }
}

LINK TO PREVIOUS POST

LINK TO THE CODE ON GITHUB