Thursday, September 20, 2012

Introduction

One of the reason of LINQ (Language Integrated Query) being so popular is that it offers so much flexibility to query through the in-memory collection. In this article, I shall explain frequenlty used extension methods of LINQ from System.Linq namespace.

Prerequisite

In order to understand this article, I assume that reader has basic knowledge of generic list collections and lamda expressions.

Lets get the datasource first

In order to demonstrate the use of extension methods, I have parepared a sample database table called "SampleTutorials" that has AutoId, Name, Address, City and Phone columns and then I have created a Sample class.
I have following method that retrieves the data from database and add into the generic list collection and returns that collection.
/// <summary>
/// Get list of sample records
/// </summary>
/// <returns></returns>
private IList<Sample> GetSampleList()
{
IList<Sample> list = new List<Sample>();
string sql = "SELECT * FROM SampleForTutorials ORDER BY AutoId DESC";
using (DataTable table = new DataTable())
{
// get the data now
using (SqlConnection conn = new SqlConnection(_connStr))
{
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.CommandType = CommandType.Text;
conn.Open();
// get the data first
using (SqlDataAdapter ad = new SqlDataAdapter(cmd))
{
ad.Fill(table);
}
conn.Close();
}
foreach (DataRow row in table.Rows)
{
list.Add(new Sample() { Address = row["Address"].ToString(), AutoId = int.Parse(row["AutoId"].ToString()), City = row["City"].ToString(), Name = row["Name"].ToString(), Phone = row["Phone"].ToString() });
}
}
}
return list;
}
Above method is called from Page_Load method like this
IList<Sample> list = GetSampleList();
I have used above list collection variable to show how the LINQ extension method works.
Get solutions of your .NET problems with video explanations, .pdf and source code in .NET How to's.

Frequently used LINQ Extension methods


SartsWith

StartsWith extension method is used to retrive all records from the collection whose a particular field starts with certain characters or string. In my case, I want to retrieve all records whose Phone field starts with "Phone" and I will get all 5 records as this condition is satisfied by all 5 records in my database table.
// select all records whose Phone starts with "Phone"
var query1 = from sample in list
where sample.Phone.StartsWith("Phone")
select sample;
Output:

Average

Average extension method is used to get the average of a particular column from the collection objets. In my case I want to get the average of AutoId, so I have specified it using lamda expressions (=>).
// gets the average of the specified column
var average = query1.Average(s => s.AutoId);

Contains

Contains extension method is used to retrieve all objects from the collection whose field contains specified string. In my case I want to get all records whose Address contains "Nagar"
var query2 = from smp in query1
where smp.Address.Contains("Nagar")
select smp;
Output:

Concat

Concat is used to concatenate two collections. In my case I am concatenating query2 into query1 and storing into queryConcat variable.
// Concates two collections of same type into onevar queryConcat = query1.Concat(query2);
Output:

Distinct

Distinct extension method is used to get the distinct records from the collection (similar to sql server distinct keyword). In my case I will get all 5 records as all 5 are distinct as displayed in the first picture above.
// Distinct - gives distinct record
var distinctRecords = queryConcat.Distinct();

ElementAt

ElementAt extension method is used to get the element (object) from the specified position in the collection. In my case I have specified 3 so this will give me the element at the 4th position (as it uses 0 based index), refer the 1st picture at the top and it will give me the record with AutoID = 7.
In case the position you have specified doesn't exsits in the collection, it throws error. To avoid error use next method.
// ElementAt - gives the record that is at nth position in the collection, if nth position doesn't exsits then throw error
var samp = query1.ElementAt(3);

ElementAtOrDefault

ElementAtOrDefault extension method is used to retrieve the specified position element from the collection and if specified position doesn't exists then it returns null.
// ElementAtOrDefault - gives the record that is at nth position in the collection if not found then returns null
var samp1 = query1.ElementAtOrDefault(4);

Except

Except extension method is used to retrieve all records from the collection that doesn't have in the second collection.
// Except - Get the list of collection that doesn't contain records from specified collection
var exceptColl = query1.Except(query2);
Output:

First

Gives first record from the collection, if collection doesn't have any object then throws error. To avoid error, use next method.
// First - gives first record from the collection, if doesn't exsits then throws error
var first = query1.First();

FirstOrDefault

FirstOrDefault extension method is used to retrieve the first element from the collection, if not then gives null.
// FirstOrDefault - if record exsits then gives first record from the collection else returns nullvar firstDefault = query1.FirstOrDefault();

GroupBy

GroupBy extension method is used to retrieve the records grouped by specified field. In this case, it will return records grouped by City field.
// GroupBy - filters records grouping by a column valuevar groupBy = query1.GroupBy(s => s.City); 

Intersect

Intersect extension method is used to retrieve the common records from two collections. In my case I have retrieved all records that is common in query1 and query2.
// Intersect - gives common records from two same types of collectionsvar intersect = query1.Intersect(query2);

Join

Join extension method is used to join two collections, I found this post very useful in understanding the Join method of LINQ http://byatool.com/c/linq-join-method-and-how-to-use-it/

Last

Last extension method gives last element from the collection. If there is no element in the collection, it throws error.
// Last - gives last record from the collection, if not throws errorvar last = query1.Last();

LastOrDefault

LastOrDefault extension method gives the last element form the collection, if not gives null.
// LastOrDefault - gives last or default record from collection, if no records then gives nullvar lastOrDefault = query1.LastOrDefault();

Count and LongCount

Count and LongCount gives the count of elements from the collection, if no parameter passed then gives total number of elements from the collection else givers count of elements that meet the filter criteria. In this case I am trying to count the elements whose City is "Kolkata".
LongCount does the same work as Count, however gives System.Int64 value.
// Count - returns the total number of records in the collection, if passed the parameter then returns the count that satisfies the conditionvar kolCount = query1.Count(s => s.City == "Kolkata");

// LongCount does the same function that Count does however it is used to count large number of records
var kolLongCount = query1.LongCount(s => s.City == "Kolkata");

Max

Max gives the maximum value of the specified field from the collection. In this case I am trying to retrieve the maximum value of the AutoId column so I will get 16.
// Max - returns the record that has maximum value in the specified column
var max = query1.Max(s => s.AutoId);

Min

Min gives the minimum value of the specified field from the collection. In this case I am trying to retrieve the minimum value of the AutoId so I will get 4.
// Min - returns the record that has minimum value in the specified columnvar min = query1.Min(s => s.AutoId);

OrderBy

OrderBy extension method is used to sort the collection on specified field. In this case I am sorting the collection on Name. It sorts the collection in ascending order.
// OrderBy - sort the collection in ascending order
var query1 = query1.OrderBy(sample => sample.Name);

OrderByDescending

OrderByDescending extension method is used to sort the collection in descending order on specified field. In this case I am sorting the collection in descending order on Name.
// OrderByDescending - sort the collection in ascending ordervar query1 = query1.OrderByDescending(sample => sample.Name);

ThenBy

ThenBy is used with OrderBy or OrderByDescending. It is used to apply sorting on already sorted collection using OrderBy or OrderByDescending. For example, in my case I am first sorting the collection by Name and then by City.
// OrderBy.ThenBy - sort the collection in ascending ordervar query1 = query1.OrderBy(sample => sample.Name).ThenBy(s => s.City);

Reverse

Reverse is used to reverse the order the objects in collection.
// Reverse - Reverse the order of the elements in the collection
var reverseList = query1.Reverse();
Output:

SequenceEqual

SequenceEqual extension method is used to determine if both collections sequence are equal. In this case the order of the elements will be different in query1 and reverseList so I will get isEqual = false.
// SequenceEqual - determines if both the collections sequences are same
var isEqual = query1.SequenceEqual(reverseList);

Skip

Skip extension method is used to skip first nth elements from the collection. In this case, I am skipping first 2 elements from the collection and will get rest of them.
// Skip - skips first nth records var skip = query1.Skip(2);
Output:

SkipWhile

SkipWhile extension method is used to skip the elements that satisfies the given filter criteria till it doens't get any element that doesn't satisfy. For example, if you have 5 records where 1st and 2nd records City is "Hyd", 3rd record City is "New York" and remaining two records City is again "Hyd" again. It will give you last 3 records.
// SkipWhile - skips records while a certain condition is met and returns remaining records// this also returns record that has met the condition but exists in the collection after the position the loop has broken
var skipWhile = query1.SkipWhile(s => s.City.Contains("City"));
Output:

In this case, first two records had City contains "City" word so it skips first two records but kept the 4 record because 3rd record doesn't have "City" in the City field.

Sum

Sum extension method gives the sum of specified field. In my case I am getting sum of AutoId that will be 51.
// Sum - sums up the specified column
var sum = query1.Sum(s => s.AutoId);

Take

Take extension method is used to take specified number of elements from the collection. In my case, I am getting top 3 elements from the collection.
// Take - takes n number of recordsvar take = query1.Take(3);

Custom paging using Linq

You can use Skip and Take extension methods to do custom paging using LINQ that has been explained in this post http://www.dotnetfunda.com/codes/code874-custom-paging-using-linq-.aspx
Repeater1.DataSource = products.Skip(startRowIndex).Take(pageSize);

Repeater1.DataBind();
In this case, Repeater control is getting the custom paged data from the products collection.
I have found another great collection of LINQ samples at MSND - http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx. You can download the source code of this article from the download link available at the top of this article.

Conclusion

LINQ is a wonderful ways to retrieving data from in-memory collection objects, its SQL like keyword and syntax makes it easier for developer having little knowledge of SQL. Hope this article was useful. Thanks for reading. Happy learning and sharing!

Sunday, September 16, 2012


LINQ to SQL Introduction with simple example, LINQ SELECT and INSERT Queries in .Net

by 4MicrosoftSolutions 19. February 2012 02:50
LINQ to SQL is a component of LINQ and part of ADO.NET that provides a run-time infrastructure for mapping relational data as objects. In this article we discuss about LINQ to SQL with simple example which has LINQ Select and Insert queries.

The .NET Framework provides ADO.NET, a platform for accessing data sources such as SQL Server and XML as well as other data sources exposed through ODBC and OLE DB. Even though it is great technology, it has some limitations, such as sometimes being overly complex. While LINQ to SQL may not offer any speed advantages over previous or existing technology, it does offer the capability to build applications more quickly and efficiently.

Before going to create sample asp.net web application, Open SQL Server management studio and create emp database and empInfo table by using following SQL script.

USE [emp]

GO

/****** Object:  Table [dbo].[empInfo]    Script Date: 02/19/2012 15:03:53 ******/

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

SET ANSI_PADDING ON

GO

CREATE TABLE [dbo].[empInfo](

          [Id] [int] IDENTITY(1,1) NOT NULL,

          [Name] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,

          [Role] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,

          [JoiningDate] [datetime] NOT NULL,

 CONSTRAINT [PK_empInfo] PRIMARY KEY CLUSTERED

(

          [Id] ASC

)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]

) ON [PRIMARY]



GO

SET ANSI_PADDING OFF

Now open visual studio, create asp.net web site. Right click on Solution explorer and select Add New Item => select LINQ to SQL Classes and name it as EmpData.dbml. Open Server Explorer=> Right Click on Server Explorer =>Select Add Connection and mention data base server name and database name just before you created(that is database name is emp here) .

Expand emp database in Server explorer, drag and drop empInfo table on to EmpData.dbml.
Then add below code to Default.aspx page which Employee Input form and Employee grid which displays all employee information from database table empInfo.

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title>LINQ to SQL Example</title>

</head>

<body>

   <form id="form1" runat="server">

    <div>

        <div>

            Name:<asp:TextBox ID="txtName" runat="server"></asp:TextBox><br /><br />

            Role:<asp:TextBox ID="txtRole" runat="server"></asp:TextBox><br /><br />

            <asp:Button ID="btn" runat="server" Text="Submit" onclick="btn_Click" />

       </div>

       <br /><br />

       <div>

            <asp:GridView ID="gvEmp" runat="server"></asp:GridView>

       </div>

    </div>

    </form>

</body>

</html>

Add below code to Default.aspx.cs file which inserts the employee information to empInfo database table and displays all employees’ information from empInfo database table.

using System;

using System.Configuration;

using System.Data;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;


public partial class _Default : System.Web.UI.Page
{
    EmpDataDataContext db = new EmpDataDataContext();
    protected void Page_Load(object sender, EventArgs e)
    {
        if (Page.IsPostBack == false)
            BindEmpData();
    }

    protected void btn_Click(object sender, EventArgs e)
    {
        empInfo objEmp = new empInfo();

        objEmp.Name = txtName.Text;
        objEmp.Role = txtRole.Text;
        objEmp.JoiningDate = DateTime.Now;

        db.empInfos.InsertOnSubmit(objEmp);
        db.SubmitChanges();

        BindEmpData();
    }

    void BindEmpData()
    {
        var empData = from emp in db.empInfos
                             select emp;

        gvEmp.DataSource = empData;
        gvEmp.DataBind();
    }
}

As shown above, create object for database context EmpDataDataContext. To submit employee information to SQL Server Database, create object for empInfo database table which provided as class in EmpDataDataContext.dbml file. Provide the input for Name, Role and JoiningData and submit empInfo object to datacontext EmpDataDataContext object by using InsertOnSubmit() method. Now submit all the data to database by using SubmitChanges() method of EmpDataDataContext object.

To display the all employees information write the simple select query on empInfos class of EmpDataDataContext object as shown below.

var empData = from emp in db.empInfos
                      select emp;

Provide this data source to gridview DataSource property and the output display as shown below.


Configuring Session State in Asp.Net, InProc, StateServer, SQLServer Session Modes in Asp.Net

by 4MicrosoftSolutions 5. February 2012 05:41
There are different ways to store session in Asp.Net. You can choose any option based on your application requirements.

Asp.Net 3.5 provides five different modes to store session state. Those are Off, InProc, StateServer, SQLServer, Custom. By default Asp.Net takes InProc as default mod to store session state. Here we discuss about each mode in-detail.

Session State Mode Off:
You can apply this option whenever you application not using session to store any data. That means by applying session mode to Off, you are disabling session for your application. You can set session mode to Off in your application by adding sessionState element in your web.config file and making mode attribute to Off as shown below.

<system.web>

    <sessionStatemode="Off"/>

………………………….

</system.web>


Session State mode InProc:
This is default session state mode in Asp.Net. In this mode session state stored in memory in the same process as Asp.Net process runs. The advantage of session state mode InProc is by using this mode your application becomes very fast because it picks the session state information very quickly (because it is in the same process).

You can set session state as InProc in web.config file as shown below.

<system.web>

    <sessionStatemode="InProc"timeout="120" />

………………………….

</system.web>

Here timeout is number of minutes session has to store the information (after timeout you lost all information stored in session).

But there are some disadvantages by using session mode as InProc. First one is, by storing the session state in InProc (that means in same process as Asp.Net Process runs) if your application restarts, then all session information lost. Second disadvantage is, whenever you use session state mode as InProc, that means if you store session state within the web server you cannot run your application on a web farm (that means you cannot run your application on multiple server).

You can avoid all these disadvantages by changing the session state mode to other options.

Session State mode StateServer:
If you change the session state mode to StateServer, session stores in window NT process instead of Asp.Net Process. That means your isolating the session state from your application. Even though your application restarts, you will not lose any session information. You can store the session information in window NT process of same server or different server by changing session mode to StateServer. By storing the session information in window NT process of different server, you can make application to run on web farm.

For example if you want to run your application on web farm which has five servers, in those servers you can use one server to store the session state and remaining will use that server for session information by applying proper settings.

You have to make two things to run your application on session state mode StateServer.

First one, you have to start the ASP.NET State Service. You can do it by entering Services.msc in your run window and press enter, then services window prompt. Now start the ASP.NET State Service and change the Startup Type to Automatic so that the service starts automatically every time that you reboot your machine as shown below.




Second one, you have to configure your application to work on session state mode StateServer. For that make changes to web.config file as shown below.

<system.web>

  <sessionStatemode="StateServer" stateConnectionString="tcpip=localhost:81" stateNetworkTimeout="10" /> 

    <machineKeydecryption="AES"validation="SHA1"     decryptionKey="A2CF54CF844940C08D44BB251D4045E72B8042AD7B8B6543267D56DFFF9141CF"    validationKey="EDD897FE43DB7AF34BD189351F8ACE8A478486A1C0E3C3944FBFF466294BCE26EE4
                     62596DA599AD48F1A0C99C9A92CEB414281FEFAAD233222A9547ED095F805"
    />

………………………….

</system.web>

As shown above, you have to mention connection string for stateConnectionString attribute if you want to store session state in other web server window NT process. And we included the machineKey element in web.config file. If you want to run your application (on web farm), and you need to use the same State Server to store Session state all other servers in web farm. For that you need to specify explicit encryption and validation keys. You need not to include a machineKey element when the State Server is hosted on the same machine as your ASP.NET application. I will explain in next article about machinekey, about decryption, validation attributes and how to generate decryption and validation keys.

If your application is running under session state mode InProc and you want to shift it State Server mode, no need to change anything in your code. Just apply the settings as mentioned above.  

Session State mode SQLServer:
You can store session state information in your SQL Server data base by applying session state mode to SQLServer. It will give same advantages as StateServer mode gives.

To store session state in SQL Server, you have to complete following steps. First one, configure your data base server to support SQL Server session state and second one, configure your application to use SQL Server Session state.

To add necessary tables in your data base to store session state, you can use aspnet_regsql tool which is generally located at C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regsql.exe.

Execute the following command on your server by mentioning the your data base server name.

aspnet_regsql -C “Data Source=localhost;Integrated Security=True” –ssadd

Here I mentioned my data base server name as localhost. By executing above command, a new data base ASPState is created with necessary tables and stored procedures in given data base server.By default session state stored in tempDB database, to change the session storage data base to ASPState execute following command.

aspnet_regsql -C “Data Source=localhost;Integrated Security=True” -ssadd -sstype p

Notice that this command includes a -sstype p switch. The p stands for persistent. Session state that is stored in the ASPState database is called persistent Session state because it survives database server restarts.

If you want to store Session state in a custom database, execute following command to store Session state in a database named MyDataBase.

aspnet_regsql -C “Data Source=localhost;Integrated Security=True”-ssadd -sstype c -d MyDataBase

By executing this command creates a new database named MyDataBase that contains both the tables and stored procedures for storing Session state. Notice that the -sstype switch has the value c for custom. The command also includes a -d switch that enables you to specify the name of the new database.

If you want to remove the Session state tables and stored procedures from a server, then you can execute the following command:

aspnet_regsql -C “Data Source=localhost;Integrated Security=True” –ssremove

Executing this command removes the ASPState database. It does not remove a custom Session state database. You must remove a custom database manually.

After configuring your data base to store session state, now configure your application to store session state by making changes to web.config file as shown below.

<system.web>

    <sessionStatemode="SQLServer"sqlConnectionString="Data Source=localhost;Integrated Security=True"sqlCommandTimeout="30" />

    <machineKeydecryption="AES"validation="SHA1"
    decryptionKey="A2CF54CF844940C08D44BB251D4045E72B8042AD7B8B6543267D56DFFF9141CF"    validationKey="EDD897FE43DB7AF34BD189351F8ACE8A478486A1C0E3C3944FBFF466294BCE26EE4
                      62596DA599AD48F1A0C99C9A92CEB414281FEFAAD233222A9547ED095F805"
   />

………………………….
</system.web>

Pass your ASPState data base connection string where you are storing the session state information for sqlConnectionString attribute and timeout period for sqlCommandTimeout.

If you want to store session state in custom data base change sqlConnectionString and apply allowCustomSqlDatabase attribute as true as shown below.

<system.web>

<sessionStatemode="SQLServer"sqlConnectionString="Data Source=YourServer;Integrated Security=True;database=MyDataBase"sqlCommandTimeout="30"allowCustomSqlDatabase="true"/>

   <machineKeydecryption="AES"validation="SHA1"
    decryptionKey="A2CF54CF844940C08D44BB251D4045E72B8042AD7B8B6543267D56DFFF9141CF"    validationKey="EDD897FE43DB7AF34BD189351F8ACE8A478486A1C0E3C3944FBFF466294BCE26EE4
                     62596DA599AD48F1A0C99C9A92CEB414281FEFAAD233222A9547ED095F805"
     />

………………………….

</system.web>