Understanding LINQ

why we should use IEnumerable as return type  : IEnumerable helps to iterate over a collection without knowing the actual datatype. It acts just like an ABSTRACTION - without knowing actual type

Also may be IEnumerable is the base class of all the collections classes (both generic and non-generic) [ List, ArrayList, Dictionary, HashTable etc]



LINQ (Language integrated query) - Using this we can write common code(common query syntax) to fetch data from different data sources. Data sources means it can be from 

  • Database like Sql server, oracle etc.
  • XML files
  • In memory objects like Lists, Arrays, collections
The above is an advantage. Disadvantage are below
  • It is quite difficult to write complex queries like we write in Sql server
  • We might get performance issues in case if we do not write queries properly
  • There is no cached plans like we do in Sql server

Each query is a combination of three things. They are as follows:

  1. Initialization (to work with a particular data source)
  2. Condition (where, filter, sorting condition)
  3. Selection (single selection, group selection, or joining)
LINQ can be written in three ways

  1. Method Syntax
  2. Query Syntax
  3. Mixed Syntax
1.Method Syntax




2.Query syntax


 

 


3. Mixed Syntax




In LINQ, the operators are divided into the following categories:

  1. Projection Operators
  2. Ordering Operators
  3. Filtering Operators
  4. Set Operators
  5. Quantifier Operators
  6. Grouping Operators
  7. Partitioning Operators
  8. Equality Operators
  9. Element Operators
  10. Conversion Operators
  11. Concatenation Operators
  12. Aggregation Operators
  13. Generation Operators
  14. Join Operators
  15. Custom Sequence Operators
  16. Miscellaneous Operators
Projection Operators

projection - it is used to select the data from the data sources. 
  • we can select the data in its original form. I mean as it is.
  • we can select the data by doing some arithmetic  operations on it
  • we can select the data in a total new form using anonymous function.
 I mean either selecting one or two properties out of 10 properties for example then you must use 
anonymous function. If in case if you are selecting only column or every column then no need of anonymous function

Remember that if you want select all columns or single column then we don't use anonymous type.
We should use anonymous type if and  only if we want more than one column. IMPORTANT ** - inside anonymous, it should be assigned to some variable or it should directly come from classobject.member

It contains two methods
  • Select
  • SelectMany
Select - This is used to select the data from the data source in the fashion highlighted in the above three bullet points.

TSource -> Input data source
TResult and TKey -> the data type of this will be know from our lambda expression returns.

Always just look at Func<TSource,TResult>

select takes two parameters by theory but by practical it takes only one Func<TSource,TResult> parameter

IEnumerable<TSource> ====>Data Source on which we are going to write or execute the Func delegate expression. Actually DONT CONCENTRATE ON THIS PARAMETER. ThIS IS ONLY FOR THEORY

Func<TSource,TResult> =====> This is Func delegate expression that will be executed on each and every element of datasource [here it is Tsource]


IF YOU SEE IN THE ABOVE IMAGE PRACTICALLY, IT IS TAKING ONLY ONE PARAMETER AND THAT IS 
Func<TSource,TResult> or Func<TSource,int,TResult>




Method1 : Select<TSource,TResult>(IEnumerable<TSource>, Func<TSource,TResult>)
                   -TSource -> Input data source
                    TResult -> the data type of this will be know from our lambda expression returns.

Ex : string[ ] names = {"Tom", "Dick" "Harry"};
var result = names.Select (n => n.Length);

Here in the above example, the compiler can understand the data type of TResult only from the return value of the lambda expression. In this case, n.Length returns an integer value so TResult will have data type of integer.



Method2: Select<TSource,TResult>(IEnumerable<TSource>, Func<TSource,Int32,TResult>)


Examples : 

Overload 2 that taking Index


Overload 1 without taking Index - 



Note: There is no intellisense support since we are using a dynamic type. And we need to remember the property name and type also.

===================================================================================


selectMany - This is same as select method. Difference is : Ex: If you have an student object, where each student has some properties with normal datatypes like

studentID -->int
studentName -->string
studentClass -->int

But we know that each student has to study more than one subject so to store more than one subject of an student then we need to store it in collection generic variable ex: List<subjects>.

So in this student context, we have below properties

studentID -->int
studentName -->string
studentClass -->int
List<subjects> --> collection type.

so when ever we find such context to get the details of an object which has collection properties in it then we have to use selectMany.

we can also use selectMany to split the strings into characters scenarios.

/*IMP POINT: Func output result is also inferred from the output of lambda expression. If we give string as output then the return type will be of type string 
* Ex: Func<string, char, string> func2 = (data, func1) => $"{data}-->{func1}";
* There is no such rules like we need to project to new anonymous types like we saw in our previous examples**/

ex:       Func<Student, List<string>> func = (student) => student.Programming.ToList();
            var result = Student.GetStudents().AsEnumerable().SelectMany(func);


selectMany has 4 overload out of which we mainly discuss most important overloads

NOTE : Think TResult, TSource, TCollection just as an normal datatypes like string,int,float,decimal,double etc without storing inside the collections or arrays untill unless it is as mentioned as IEnumerable<TResult> or IEnumerable<TSource> or IEnumerable<TCollection>



Overload 1 without taking Index with one FUNC - 

SelectMany<TSource, TResult>(Func<TSource, IEnumerable<TResult>> selector);

selectMany without index and one Func-->It will loop through each item and then collect its listofvalues or arrayofvalues or array. Once looping is finished, then it merges each listOFValues into one list.



Overload 2 with taking Index with one FUNC - 
SelectMany<TSource, TResult>(Func<TSource, int, IEnumerable<TResult>> selector);

selectMany with index and one Func-->It will loop through each item and then collect its listofvalues and its index. Once looping is finished, then it merges each listOFValues into one list. Later on that list we can use select method to concat index on each listofvalues . Becuase we cannot specify ananymous method in this overload


Overload 3 without taking Index with 2 FUNC - 
SelectMany<TSource, TCollection, TResult>(Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector);

selectMany without taking index and twoFunc--> first FUNC1 : It will loop through each item and then collect its listofvalues. Once looping is finished, then it merges each listOFValues into one list. second FUNC : on the previous FUNC1 result, we can write what ever expression we need to get our formatted result.

ex1 : on the previous FUNC1 result, we can write like print student name and their respective subjects in any format like 
(student, list) => $"{student.Name} ====>{list}";

ex2: on the previous FUNC1 result, we can project it to new ananymous type and assign student name and their respective subjects
to new variables. (student, list) => new { name = student.Name, subject = list };




every types [ simple datatypes and complex datatypes like class] directly inherit from system.object [ ==>this system.object class contains few mthods like GetHascode(),Equals(),ToString() ] 

virtual -->there is already default implementation given 


orderby firstname, orderby lastname
------------------------------------------------------

why we need this is ex: suppose there are peoples who firstname is same but last name is different.


After sort, it will become like below


Suppose if first name is same and last name is ordered already then it wont sort. Ex: see Pranaya data
its not sorted because it is already sorted

Comments

Popular posts from this blog

Understanding Collection and Object Initializer

How to execute Javascript in VS code