Tuesday, September 25, 2012

Comparison of Execution Time taken by LINQ, FOR loop and FOREACH loop

While developing any kind of web/windows application we come across a point where we are supposed to filter records based on some criteria from bunch of data. And to define logic we may use LINQ query or FOREACH or FOR looping structure without considering the amount of data and execution time for obtaining result set.

Let’s consider that we developing a utility application/business logic which processes data. Below is demo application to check execution time of LINQ queries, FOREACH and FOR loop.

Here I am generating ONE CRORE random numbers between 0 to 100 and adding it to list and calculating occurrences of “20” number from the random number generated list.

static void Main(string[] args)
        {
            //Generating ONE CRORE random numbers
            List<int> data = new List<int>();
            System.Random rnd = new Random();
            for (int i = 0; i <= 10000000; i++)
            {
                data.Add(rnd.Next(100));
            }

            //Filtering by different methods
            Console.WriteLine("Execution time using different methods." + Environment.NewLine);
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            int count = 0;

            //------------------------------------------------
            //Method - 1: Using LINQ Query
            sw.Start();
            
            count = (from d in data
                     where d == 20
                     select d).Count();

            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds + " milliseconds - Using LINQ query");

            sw.Reset();

            //------------------------------------------------
            //Method - 2: Using LINQ lambda expression            
            sw.Start();
            
            count = data.Where(c => c == 20).Count();

            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds + " milliseconds - Using LINQ Lambda expression");

            sw.Reset();            

            //------------------------------------------------
            //Method - 3: Using FOR loop
            count = 0;
            sw.Start();     
       
            for (int i = 0; i < data.Count; i++)            
                if (data[i] == 20)
                    count++;            
            
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds + " milliseconds - Using For loop");

            sw.Reset();  

            //------------------------------------------------
            //Method - 4: Using FOREACH loop
            count = 0;
            sw.Start();

            foreach (var item in data)
                if (item == 20)
                    count++;

            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds + " milliseconds - Using Foreach loop");           
            Console.Read();
        }


In above example we used four different methods to calculate occurrences of number “20” in random number list:
  • Method – 1: Using LINQ query 
  • Method – 2: Using LINQ lambda expression 
  • Method – 3: Using FOR loop 
  • Method – 4: Using FOREACH loop 

And from the above output we can see that LINQ query creates more overhead with compared to looping controls rather FOREACH loop.

Hence, lesser execution time more faster and optimized output.

Learn by diving in Programming Ocean...
Happy Programming!!!

Wednesday, July 18, 2012

String value to ENUM type conversion

Download sample code
An enumeration type (also named an enumeration or an enum) provides an efficient way to define a set of named integral constants that may be assigned to a variable. By using enum you can clearly specify for the client code which values are valid for variable.

Also in some cases we may come across storing the enum value in form of string value, which further needs to be converted to enum type so that business logic remains consistent and error free.

While converting string to enum type we can use Enum.Parse() or Enum.TryParse()independently wherever its required. Now this kills re-usability feature of OOP.

Taking advantage of re-usability I have created generic method which will be accepting string value and expected type of enum in form of template T.

Below is an extension method used to convert string to enum type, however instance methods can be created too.
public static T ToEnum<T>(this string value)
{
      if (string.IsNullOrEmpty(value) && typeof(T).IsEnum)
      {
          bool result = false;
          Enum.TryParse(value, true, out result);

          if (result)
             return (T)Enum.Parse(typeof(T), value, true);
      }

      //This will return default value as 0
      return default(T);
}

In above code T is the template which we are expecting. For demo purpose I have declared two enum types namely Colors and Direction which can be passed as template T.
public enum Colors
{
      RED = 0,
      GREEN = 1,
      BLUE = 2
}

public enum Direction
{
      NORTH,
      EAST,
      WEST,
      SOUTH
}

Invoking enum conversion method.
//Calling ToEnum conversion extension method            
Colors selectedColor = "red".ToEnum<Colors>();

Direction selectedDirection = "North".ToEnum<Direction>();

Thus “red” will be converted to its relevant enum value and stored in the enum type of variable which can be used same as that of normal variable in logic. And if at all specified string is not found in enum, it will return default “0” value.

Here values of variables "selectedColor" and "selectedDirection" would be "Colors.RED" and "Direction.NORTH" respectively.

As per sample application and code output text will be shown in red color.

Learn by diving in Programming Ocean...
Happy Programming!!!

Tuesday, June 5, 2012

Using APPLY Operator

The Apply operator available in SQL Server 2005 onwards is used to invoke a table-valued function for each row returned by an outer table expression of a query. The table-valued function acts as the right input and the outer table expression acts as the left input. The right input is evaluated for each row from the left input and the rows produced are combined for the final output. The list of columns produced by the APPLY operator is the set of columns in the left input followed by the list of columns returned by the right input.

The Apply operator is similar to that of Joins but has no conditions in the query.

There are two forms of Apply operator:
  • Cross Apply
    The CROSS APPLY operator returns rows from the primary (outer) table only if the table-value function produces a result set. It's similar to that of Inner Join or Cross Join.
  • Outer Apply
    The OUTER APPLY, on the other hand, returns all rows from the outer table, even if the function produces no results. Thus, it generates NULL values for those records whose result set is not returned. It's similar to that of Outer Join.

Consider an example below to demonstrate Apply operator:

GO

CREATE TABLE [dbo].[Departments](
 [DepartmentId] [int] NOT NULL PRIMARY KEY,
 [DeparttmentName] [varchar](50) NULL,
);

GO

INSERT INTO [dbo].[Departments] VALUES(1, 'HR')
INSERT INTO [dbo].[Departments] VALUES(2, 'Marketing')
INSERT INTO [dbo].[Departments] VALUES(3, 'Finance')
INSERT INTO [dbo].[Departments] VALUES(4, 'R&D')
INSERT INTO [dbo].[Departments] VALUES(5, 'Training')
INSERT INTO [dbo].[Departments] VALUES(6, 'Gardening')


GO

CREATE TABLE [dbo].[Employees](
 [EmployeeId] [int] NOT NULL PRIMARY KEY,
 [EmployeeName] [varchar](50) NULL,
 [DepartmentId] [int] NULL REFERENCES [dbo].[Departments],
);

GO

INSERT INTO [dbo].[Employees] VALUES(1, 'Jeet', 1)
INSERT INTO [dbo].[Employees] VALUES(2, 'Sagar', 2)
INSERT INTO [dbo].[Employees] VALUES(3, 'Chirag', 2)
INSERT INTO [dbo].[Employees] VALUES(4, 'Jayesh', 3)
INSERT INTO [dbo].[Employees] VALUES(5, 'Ketan', 4)
INSERT INTO [dbo].[Employees] VALUES(6, 'Rikin', 4)
INSERT INTO [dbo].[Employees] VALUES(7, 'Pratik', 6)

GO

In above example we can see list of Departments and Employees related to departments (if any) in appropriate tables respectively.

As mentioned above, Apply operator works with table-values function (also known as TVF), consider the below example of it.
GO
CREATE FUNCTION [dbo].[GetEmployees]
(
 @DepartmentId int 
)
RETURNS 
@ResultSet TABLE 
(
 EmployeeId int,
 EmployeeName varchar(20)
)
AS
BEGIN
 INSERT INTO @ResultSet 
  SELECT EmployeeId,EmployeeName 
  FROM Employees 
  WHERE DepartmentId = @DepartmentId
 
 RETURN 
END

GO


Using CROSS APPLY
SELECT * FROM Departments
 CROSS APPLY GetEmployees(Departments.DepartmentId)

The above query returns the rows with employees assigned to departments, whereas the department wherein the employees are not assigned does not appear. Thus we can see the department "Training" is missing.


Using OUTER APPLY
SELECT * FROM Departments 
 OUTER APPLY GetEmployees(Departments.DepartmentId)

The above query returns all the rows with the outer table, whether or not the function returns data for a specific row. Thus we can see that employee value of "Training" department has NULL values.

Learn by diving in Programming Ocean...
Happy Programming!!!