Saturday, May 17, 2008

Comparing Moq to Rhino Mocks

Rhino Mocks Vs Moq

As a big believer in test driven development, I spent some time today fiddling around with Visual Studio 2008's new unit testing features. Boy is that a nice addition! As much as I have been a fan of testdriven.net, I am now convinced that there is no longer any point in using the plugin.


The Visual Studio integration makes using NUnit obsolete as well. The whole process is nicely and conveniently built into the IDE, and it is a very welcome addition indeed. The tools are infinitely better and nicer: debugging tests is trivial, grouping tests into packages is easy, and managing configuration items is equally easy.

I am also a big believer in mock frameworks. How do you expect to test functions without separating dependencies? I've worked with unit tests that are completely broken and useless because they never abstracted the data they were testing against. What good is a test that needs to be updated every month or so? Without separating dependencies, unit tests turn into gigantic messes when something fails - because you'll end up with 40 failed tests and no clear indication of where the break occurred. A nicely mocked up suit of unit tests makes it clear where something breaks, because instead of having 40 broken tests you'll have 1. It also allows you to forget about external dependencies such as databases, web services, or text files.

The API that I have used extensively, and I think a lot of other people have adopted as well, is
Rhino Mocks. This superior framework is difficult to use at first, but is incredibly powerful. The greatest thing about Rhino Mocks is that it is strongly typed, which means that all of the Visual Studio refactoring tools work with your unit tests. Without this feature, managing giant suits of tests would be infeasible. While wasting time looking through the MSDN's RSS blog today, however, I ran across an entry that pointed me towards a new framework called Moq. So, naturally, I downloaded it and started to fool around with it. It is tough to say right now which one I prefer, since they both have their advantages. The Rhino API is something I am familiar with, and is flexible enough to do whatever you want with it. Moq, on the other hand, has a very 3.5-ish feel to it, since it draws on Linq expressions and makes heavy use of lambda functions.

Let's look at an example that we can compare and contrast


/// <summary>
/// This class has methods that we will use to run some tests on.
/// </summary>

public class TestClass
{

/// <summary>
/// Gets / sets the aggregated class.
/// </summary>

public AggregatedClass AggregatedClass
{
get;
set;
}

/// <summary>
/// Call the aggregated class.
/// </summary>
/// <param name="x"></param>
/// <returns></returns>

public int Halve(int x)
{
return this.AggregatedClass.Halve(x);
}

}

...

/// <summary>
/// A class that is aggregated by another class.
/// </summary>

public class AggregatedClass
{
/// <summary>
/// Divides a number by 2.
/// </summary>
/// <param name="x">The number to divide.</param>
/// <returns>Half of the number inputted.</returns>

public virtual int Halve(int x)
{
return x / 2;
}

}

Using Rhino Mocks, you would mock the AggregatedClass and test TestClass as follows:



/// <summary>
/// Test using Rhino Mocks API.
/// </summary>

[TestMethod]
public void TestHalve1()
{
MockRepository mocks = new MockRepository();
AggregatedClass aggregatedClass = mocks.CreateMock<AggregatedClass>();

mocks.BackToRecordAll();
Expect.Call(aggregatedClass.Halve(12)).Return(6);
mocks.ReplayAll();

TestClass testClass = new TestClass();
testClass.AggregatedClass = aggregatedClass;
Assert.AreEqual(6, testClass.Halve(12));
mocks.VerifyAll();

}

Here is the Moq equivalent:


/// <summary>
/// Test using Moq API.
/// </summary>

[TestMethod]
public void TestHalve2()
{
var aggregatedClass = new Mock<AggregatedClass>(MockBehavior.Strict);
aggregatedClass.Expect(x => x.Halve(12)).Returns(6);

TestClass testClass = new TestClass();
testClass.AggregatedClass = aggregatedClass.Object;
Assert.AreEqual<int>(6, testClass.Halve(12));

aggregatedClass.VerifyAll();

}
In practice, both of these API's do the same thing. But there are a few key differences between the two. The first is that Rhino is very 'Mock-Centric', meaning that everything goes through the MockRepository object. All verifications of expectations, recording, etc., go through the MockRepository. Moq, in contrast, allows mocks to be verified individually.
In practice, I doubt this would be the way I would want to go since it is usually necessary to group mock objects into a single sequence of calls that need to be verified in unison. Fortunately, there is a way to do this using the Moq framework:


/// <summary>
/// Test using Moq API.
/// </summary>

[TestMethod]
public void TestHalve2()
{
MockFactory factory = new MockFactory(MockBehavior.Strict);
var aggregatedClass = factory.Create<AggregatedClass>();
aggregatedClass.Expect(x => x.Halve(12)).Returns(6);

TestClass testClass = new TestClass();
testClass.AggregatedClass = aggregatedClass.Object;
Assert.AreEqual(6, testClass.Halve(12));

factory.VerifyAll();

}
One thing that is unfortunate about this approach is that the behavior parameter is defined in the MockFactory class, and cannot be customized in any other location (it cannot be set via the Create method). The Rhino Mocks API supports a very essential function called PartialMock, which allows calls to go to the default implementation if no expectation is set on them. This means that Moq has an all-or-nothing approach to setting the behavior of the mocks that it creates. Of course, one can get around this by creating a mix of mock objects using a combination of techniques from both of these examples, but it becomes difficult since the global VerifyAll() call won't work for them. Partial mocks are critical when dealing with abstract classes with abstract methods. One really nice thing about Moq, however, is how it allows you to verify arguments. Take an example where I want to test that Halve is called with a positive number. How is that done with Rhino mocks? Here's one way:


private delegate bool CallbackDel(int x);

/// <summary>
/// Test using Rhino Mocks API.
/// </summary>

[TestMethod]
public void TestHalve1()
{
MockRepository mocks = new MockRepository();
AggregatedClass aggregatedClass = mocks.CreateMock<AggregatedClass>();

mocks.BackToRecordAll();
Expect.Call(aggregatedClass.Halve(12)).Return(6);

LastCall.Callback((CallbackDel)((int x) =>
{
return x > 0;
}));

mocks.ReplayAll();

TestClass testClass = new TestClass();
testClass.AggregatedClass = aggregatedClass;
Assert.AreEqual(6, testClass.Halve(12));
mocks.VerifyAll();

}
A more elegant solution, however, would be to use constraints:


/// <summary>
/// Test using Rhino Mocks API.
/// </summary>

[TestMethod]
public void TestHalve1()
{
MockRepository mocks = new MockRepository();
AggregatedClass aggregatedClass = mocks.CreateMock<AggregatedClass>();

mocks.BackToRecordAll();
Expect.Call(aggregatedClass.Halve(12)).IgnoreArguments().Return(6);
LastCall.Constraints(Is.GreaterThan(0));
mocks.ReplayAll();

TestClass testClass = new TestClass();
testClass.AggregatedClass = aggregatedClass;
Assert.AreEqual(6, testClass.Halve(6));
mocks.VerifyAll();

}
One nice thing about Moq is that it makes checking arguments a lot easier. Here's an example of how that works:

/// <summary>
/// Test using Moq API.
/// </summary>

[TestMethod]
public void TestHalve2()
{
MockFactory factory = new MockFactory(MockBehavior.Strict);
var aggregatedClass = factory.Create<AggregatedClass>();
aggregatedClass.Expect(x => x.Halve(It.Is<int>(y => y > 0))).Returns(6);

TestClass testClass = new TestClass();
testClass.AggregatedClass = aggregatedClass.Object;
Assert.AreEqual(6, testClass.Halve(12));

factory.VerifyAll();

}
The great thing about using delegates for value checking is that you can put whatever you want in there. Want to test that y is an even number? Replace

y => y > 0
...with...

y => y % 2 == 0
I think this is a much more sophisticated system than the one used in the Rhino mocks API. Sadly, it appears that there are still a lot of things left to be done. For instance, where are the ordered and unordered calls? MockFactory does not contain them, and there is no way to set a repeating value. For instance, say we want to test the following method:

/// <summary>
/// Quarters a number.
/// </summary>
/// <param name="x"></param>
/// <returns></returns>

public virtual int Quarter(int x)
{
for(int i = 0; i < 10; i++)
{
if(i % 2 == 0)
{
this.AggregatedClass.Foo(x);
this.AggregatedClass.Bar(x);
}
else
{
this.AggregatedClass.Bar(x);
this.AggregatedClass.Foo(x);
}
}

x = this.AggregatedClass.Halve(x);
return this.AggregatedClass.Halve(x);

}
This is easy with Rhino Mocks:

[TestMethod]
public void TestQuarter()
{
MockRepository mocks = new MockRepository();
AggregatedClass aggregatedClass = mocks.CreateMock<AggregatedClass>();

mocks.BackToRecordAll();
using(mocks.Ordered())
{
using(mocks.Unordered())
{
for(int i = 0; i < 10; i++)
{
aggregatedClass.Foo(12);
aggregatedClass.Bar(12);
}
}

Expect.Call(aggregatedClass.Halve(12));
LastCall.IgnoreArguments().Repeat.Any().Return(3);

}
mocks.ReplayAll();

TestClass testClass = new TestClass();
testClass.AggregatedClass = aggregatedClass;
Assert.AreEqual(3, testClass.Quarter(12));
mocks.VerifyAll();

}
Unfortunately, this is currently not possible with the Moq API. In my mind, this is a pretty serious drawback. The reality is that you need these types of order constraints in order to validate your mock calls. Hopefully, that stuff gets added in the future. The point is that there are a number of exciting things going on in the world of unit testing, and it's fun to see these API's improve. We'll see where it all ends up in a few years.

I have inspired this concept by Michael Braude Blog

Happy Coding!!!

Friday, May 9, 2008

Validation of viewstate MAC failed error

Issue Description

You can get this Exception: HttpException (0x80004005): Validation of viewstate MAC failed.

If this application is hosted by a Web Farm or cluster, ensure that configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster. when the following preconditions are true:

  1. You aren't using a web farm.
  2. It appears when using built-in databound controls such as GridView, DetailsView or FormView which utilize “DataKeyNames”.
  3. It appears if you have a large page which loads slowly for any reason.

If following preconditions are true and you click a postbacking control/link and the page hasn't loaded completely in client browser, you might get the "Validation of ViewState MAC failed" exception. When this happens, if you just try setting the page property "EnableViewStateMac" to false, it does not solve the problem, it just changes the error message in same navigation behavior: The state information is invalid for this page and might be corrupted. Other exceptions that seem to be the same problem look like:

Exception: System.Web.HttpUnhandledException
Message: Exception of type 'System.Web.HttpUnhandledException' was thrown.
Source: System.Web
at System.Web.UI.Page.HandleError(Exception e)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint,
Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint,
Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest()
at System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)
at System.Web.UI.Page.ProcessRequest(HttpContext context)
at ASP.test_aspx.ProcessRequest(HttpContext context)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExec
utionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&
completedSynchronously)

Nested Exception

Exception: System.ArgumentException
Message: Invalid postback or callback argument.
Event validation is enabled using in configuration
or <%@ Page
EnableEventValidation="true" %> in a page. For security purposes, this feature
verifies that arguments to postback or callback
events originate from the server control that
originally rendered them. If the data is valid
and expected, use the
ClientScriptManager.RegisterForEventValidation
method in order to register the postback or
callback data for validation.
Source: System.Web
at System.Web.UI.ClientScriptManager.ValidateEvent(String uniqueId, String
argument)
at System.Web.UI.Control.ValidateEvent(String uniqueID, String eventArgument)
at System.Web.UI.WebControls.TextBox.LoadPostData(String postDataKey,
NameValueCollection postCollection)
at System.Web.UI.WebControls.TextBox.System.Web.UI.IPostBackDataHandler.LoadPostData(St
ring postDataKey, NameValueCollection postCollection)
at System.Web.UI.Page.ProcessPostData(NameValueCollection postData, Boolean
fBeforeLoad)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint,
Boolean includeStagesAfterAsyncPoint)

and
Content-Length:1232
Content-Type:application/x-www-form-urlencoded
Accept:*/*
Accept-Encoding:gzip,deflate
Accept-Language:en-us
Cookie:ASP.NET_SessionId=skk4vriy1lzghm55bicesz45;
Host:
User-Agent:T-Mobile Dash Mozilla/4.0 (compatible; MSIE 4.01; Windows CE;
Smartphone; 320x240) UA-OS:Windows CE (Smartphone) - Version 5.1
UA-color:color16
UA-pixels:320x240
x-wap-profile:""
UA-Voice:TRUE
UA-CPU:x86
X-Forwarded-For:

Thread: 964
Date: 2007-10-25 13:47:03,925
NDC: (null)

Exception: System.Web.HttpException
Message: Validation of viewstate MAC failed.
If this application is hosted by a Web
Farm or cluster, ensure that configuration
specifies the same validationKey and validation
algorithm. AutoGenerate cannot be used in a cluster.
Source: System.Web
at System.Web.UI.ViewStateException.ThrowError(Exception inner, String
persistedState, String errorPageMessage, Boolean macValidationError)
at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString)
at
System.Web.UI.ObjectStateFormatter.System.Web.UI.IStateFormatter.Deserialize(String
serializedState)
at System.Web.UI.Util.DeserializeWithAssert(IStateFormatter formatter, String
serializedState)
at System.Web.UI.HiddenFieldPageStatePersister.Load()
at System.Web.UI.Page.LoadPageStateFromPersistenceMedium()
at System.Web.UI.Page.LoadAllState()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint,
Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint,
Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest()
at System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)
at System.Web.UI.Page.ProcessRequest(HttpContext context)
at ASP.test_aspx.ProcessRequest(HttpContext context)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExec
utionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&
completedSynchronously)

Nested Exception

Exception: System.Web.UI.ViewStateException
Message: Invalid viewstate.
Client IP:
Port: 61362
User-Agent: T-Mobile Dash Mozilla/4.0 (compatible; MSIE 4.01;
Windows CE; Smartphone; 320x240)
ViewState:
/wEPDwUJMjUyNTI1NDMyD2QWAmYPZBYCAgEPZBYEAlAPD2QWAh4Kb25rZXlwcmVzcwUqcmV0dXJuIGNsaWNr
QnV0dG9uKGV2ZW50LCdjdGwwMF9pYlNlYXJjaCcpZAJWD2QWBAIBD2QWBAIDDw9kFgIfAAUxcmV0dXJuIGNs
aWNrQnV0dG9uKGV2ZW50LCdjdGwwMF9jcDFfRmxhc2hCdXR0b24nKWQCBg8UKwACDxYCHghJbWFnZVVybAUj
fi9faG9tZV9hZF91bml0cy9ob21lX2FkdW5pdHMxMS5qcGdkDxQrAAMWCB4LQ29vcmRpbmF0ZXMFFzAsMCwy
NTUsMCwyMjQsMTEwLDAsMTEwHgtOYXZpZ2F0ZVVybAUGfi9uZmwvHg1BbHRlcm5hdGVUZXh0BSNUaGUgcnVz
aCB0byBGYXRoZWFkIGZvb3RiYWxsIGlzIG9uIR4GVGFyZ2V0ZRYIHwIFGzQ5OCwwLDQ1OCwxMTAsMjI0LDEx
MCwyNTUsMB8DBRB+L2hlcm9lcy9iYXRtYW4vHwQFOVRoZSBEYXJrIEtuaWdodCBpcyBoZXJlLi4uYW5kIGhl
J3MgYnJvdWdodCBzb21lIGZyaWVuZCdzIR8FZRYIHwIFGzcwOCwxMTAsNzM5LDAsNDk4LDAsNDU4LDExMB8D
BQZ+L21sYi8fBAUhTUxCIGhpdHMgYSBob21lIHJ1biB3aXRoIEZhdGhlYWQhHwVlFCsBAwICAgICAmQCAw8P
FgIeB1Zpc2libGVoZBYCAgEPZBYCZg8PZBYCHwAFMnJldHVybiBjbGlja0J1dHRvbihldmVudCwnY3RsMDBf
Y3AxX1N0YXRpY0J1dHRvbicpZBgBBR5f...

Nested Exception

Exception: System.Web.HttpException
Message: Unable to validate data.
Source: System.Web
at System.Web.Configuration.MachineKeySection.GetDecodedData(Byte[] buf, Byte[]
modifier, Int32 start, Int32 length, Int32& dataLength)
at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString)

Root Cause

This exception appears because Controls using DataKeyNames require Viewstate to be encrypted. When Viewstate is encrypted (Default mode, Auto, is to encrypt if controls require that, otherwise not), Page adds <input type="hidden" name="__VIEWSTATEENCRYPTED" id="__VIEWSTATEENCRYPTED" value="" /> field just before closing of the <form> tag. But this hidden field might not have been rendered to the browser with long-running pages, and if you make a postback before it does, the browser initiates postback without this field (in form post collection). End result is that if this field is omitted on postback, the page doesn't know that Viewstate is encrypted and causes the aforementioned Exception. I.E. page expects to be fully-loaded before you make a postback.

And by the way similar problem is with event validation since __EVENTVALIDATION field is also rendered on the end of the form. This is a security feature that ensures that postback actions only come from events allowed and created by the server to help prevent spoofed postbacks. This feature is implemented by having controls register valid events when they render (as in, during their actual Render() methods). The end result is that at the bottom of your rendered <form> tag, you'll see something like this: <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="AEBnx7v.........tS" />. When a postback occurs, ASP.NET uses the values stored in this hidden field to ensure that the button you clicked invokes a valid event. If it's not valid, you get the exception above.

The problem happens specifically when you postback before the EventValidation field has been rendered. If EventValidation is enabled (which it is, by default), but ASP.net doesn't see the hidden field when you postback, you also get the exception. If you submit a form before it has been entirely rendered, then chances are the EventValidation field has not yet been rendered, and thus ASP.NET cannot validate your click.

Workarounds

1. Set enableEventValidation to false and viewStateEncryptionMode to Never as follows:
<pages enableeventvalidation="false" viewstateencryptionmode="Never">
This has the unwanted side-effect of disabling validation and encryption. On some sites, this may be ok to do, but it isn't a best practice, especially in publicly facing sites.
;

2. Another way around the problem is to mark the form as disabled and then enable it in script once the load is complete

              function enableForm()
{
document.getElementById("form").disabled = false;
}
window.onLoad = enableForm();
Or you can disable the individual form elements and enable them once everything is loaded:
            function disableElements(elements) {
for (var i = elements.length - 1; i >= 0; i--) {
var elmt = elements[i];
if (!elmt.disabled) {
elmt.disabled = true;
}
else {
elmt._wasDisabled = true;
}
}
}

function disableFormElements() {
disableElements(_form.getElementsByTagName("INPUT"));
disableElements(_form.getElementsByTagName("SELECT"));
disableElements(_form.getElementsByTagName("TEXTAREA"));
disableElements(_form.getElementsByTagName("BUTTON"));
disableElements(_form.getElementsByTagName("A"));
}

function enableElements(elements) {
for (var i = elements.length - 1; i >= 0; i--) {
var elmt = elements[i];
if (!elmt._wasDisabled) {
elmt.disabled = false;
}
else {
elmt._wasDisabled = null;
}
}
}

function enableFormElements() {
enableElements(_form.getElementsByTagName("INPUT"));
enableElements(_form.getElementsByTagName("SELECT"));
enableElements(_form.getElementsByTagName("TEXTAREA"));
enableElements(_form.getElementsByTagName("BUTTON"));
enableElements(_form.getElementsByTagName("A"));
}
Make sure that the variable _form is set to the ASP.net form on the page. Then just call enableFormElements() and disableFormElements().

3. The last way to workaround this problem is to override the Render Event of the page to place the hidden fields for Encrypted Viewstate and Event validation on the top of the form. This will ensure that these things get written out before anything that can submit the form:


protected override void Render(System.Web.UI.HtmlTextWriter writer) {
System.IO.StringWriter stringWriter = new System.IO.StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
base.Render(htmlWriter);
string html = stringWriter.ToString();
string[] aspnet_formelems = new string[5]; aspnet_formelems[0] = "__EVENTTARGET";
aspnet_formelems[1] = "__EVENTARGUMENT";
aspnet_formelems[2] = "__VIEWSTATE";
aspnet_formelems[3] = "__EVENTVALIDATION";
aspnet_formelems[4] = "__VIEWSTATEENCRYPTED";
foreach (string elem in aspnet_formelems)
{
//Response.Write("input type=""hidden"" name=""" & abc.ToString & """")
int StartPoint = html.IndexOf("<input type=\"hidden\" name=\"" + elem.ToString() + "\"");
if (StartPoint >= 0) {
//does __VIEWSTATE exist? int EndPoint = html.IndexOf("/>",
StartPoint) + 2; string ViewStateInput = html.Substring(StartPoint, EndPoint - StartPoint);
html = html.Remove(StartPoint, EndPoint - StartPoint); int FormStart = html.IndexOf("<form");
int EndForm = html.IndexOf(">", FormStart) + 1;
if (EndForm >= 0) html = html.Insert(EndForm, ViewStateInput);
}
}
writer.Write(html);
}

There are many workarounds for the above mentioned problem; however no definite solution.
Happy programming!!!

How to retrieve permanently deleted mail in outlook

How to retrieve permanently deleted mail in outlook Worried?? Just because you accidentally deleted an important mail from your outlook inbox? Well here is a way you can get it back Don't worry if you have deleted any mails permanently from your outlook inbox. Here is a way you can retrieve your permanently deleted mails.

1. Go to Run by clicking on Start and type in regedit.



2. Now go to HKEY_LOCAL_MACHINE, expand Software.

3. You will find Microsoft there. Expand Microsoft.


4. Expand exchange and then client.

5. You will find Options there. Right click on Options, choose New and click on D Word Value.

6. Now right click the new Dword Value and rename it to DumpsterAlwaysOn. Note: This is case sensitive.

7. Right click on the DumpsterAlwaysOn and modify the Value data to 1 and click on OK. When you type 1, this means the Recovery deleted Item is on. Also 0 to turn it off.
8. Now open Outlook and click on Tools.
9. Choose 'Recovery Deleted Items'.

Saturday, May 3, 2008

An introduction to LINQ

SQL is dead. With the release of Microsoft LINQ to SQL, developers should no longer work directly with ADO.NET or SQL. With simple examples, Stephen Walther shows you how to build database-driven ASP.NET applications by taking advantage of LINQ to SQL. Most of the blood, toil, tears, and sweat that an ASP.NET developer experiences while building a web application is associated with writing the data access code.
Microsoft introduced LINQ to SQL with .NET Framework 3.5 to reduce the work that a developer must perform when accessing a database. LINQ to SQL makes it much easier to write both simple and complex database-driven websites.Writing data access code is difficult because it forces you to bridge two very different universes: the object universe and the relational universe. Your application logic (your C# or Visual
Basic .NET code) inhabits the object universe, whose basic elements are classes and objects. The basic elements of the relational universe, on the other hand, are tables and rows.You interact with the two universes by using two very different languages.
The C# and Visual Basic .NET languages are used for working with objects, and the SQL language is designed for working with tables. If you want to communicate from the object universe to the relational universe, you’re forced to embed SQL strings in your C# or Visual Basic .NET code. These SQL strings are complete gibberish from the point of view of your C# or Visual Basic .NET application. So how do you bridge this divide? LINQ to SQL bridges this divide by enabling a developer to pretend that the relational universe doesn’t exist. LINQ to SQL enables you to write all of your data access code by using C# or Visual Basic .NET. You let C# or Visual Basic .NET worry about how to translate your code into SQL in the background.
Understanding LINQ
LINQ stands for Language Integrated Query. There are many different flavors of LINQ, such as the following:
  • LINQ to Objects
  • LINQ to Amazon
  • LINQ to Entities
  • LINQ over DataSets
  • LINQ to XML
  • LINQ to Flickr
  • LINQ to LDAP
  • LINQ to SQL

These various flavors of LINQ enable you to communicate with different data sources. For example, LINQ to Flickr enables you to perform queries against photos stored at the Flickr website. In this article, we’re concerned with LINQ to SQL, which is the flavor of LINQ that you’ll most likely use when communicating with a Microsoft SQL Server database. (Currently, LINQ to SQL works with Microsoft SQL Server only, and not with other databases such as Oracle or Access.) To use LINQ to SQL, your web project must target .NET Framework 3.5. New websites created with Visual Studio 2008 target .NET Framework 3.5 by default, but you can target an existing application to use .NET Framework 3.5 within Visual Studio:

  1. Right-click the name of your project in the Solution Explorer window.
  2. Select Property Pages.
  3. Click Build.
  4. Select .NET Framework 3.5 from the drop-down Target Framework list (see Figure 1). Behind the scenes, performing this action modifies your web.config file so that it contains references to the right assemblies and uses the correct version of either the C# or Visual Basic .NET language.
    Creating LINQ to SQL Entities Before you can start using LINQ to SQL in your ASP.NET application, you must first create your LINQ to SQL entities. A LINQ to SQL entity is a C# or Visual Basic .NET class that represents an entity from your database. For example, if your database contains a table named Products, you’ll create a LINQ to SQL entity named Product that represents each product from the Products database table.

    The Product class will include a property that corresponds to each column in your database table. Visual Studio 2008 makes it easy to create LINQ to SQL entities. You create LINQ to SQL entities by using the Visual Studio Object Relational Designer (see Figure 2). To create new entities, simply drag database tables from the Server Explorer/Database Explorer window onto the Object Relational Designer.

    Let’s assume that your database contains the following table named Products:
    Column Name Column Type
    Id Int (identity, primary key)
    Name Nvarchar(50)
    Price Money

Follow these steps to create a new LINQ to SQL entity that represents this database table:

  1. From the menu, select Website > Add New Item.
  2. In the Add New Item dialog box, select LINQ to SQL Classes.
  3. In the Name text box, type Store.dbml (see Figure 3).
  4. Click Add.
  5. When a warning message appears, suggesting that the LINQ to SQL classes be added to your App_Code folder, succumb to the suggestion and click Yes.
  6. When the Object Relational Designer appears, drag one or more tables onto the Designer surface from the Server Explorer/Database Explorer. After you drag the Products table onto the Designer surface, you’ll have a new entity named Product. (Visual Studio 2008 changes the name from Products to Product automatically.)
  7. The new Product entity includes a property for each of the columns in the underlying database table. You can view information about each entity property by selecting it and looking in the Properties window. For example, Figure 4 shows the values for the Id property.

Notice that Visual Studio has detected that the Id property represents a primary key and identity value automatically. In the property sheet in Figure 4, both the Primary Key property and the Auto Generated Value property have the value True. If Visual Studio ever gets this setting wrong, you can change these properties manually. For example, I add a column to all of my database tables that has a default value of GetDate(). That way, every time I add a new row to the table, the row gets a date and time stamp automatically. However, the Object Relational Designer doesn’t recognize columns with a default value as being auto-generated. Therefore, I always end up changing the Auto Generated Value property manually for these types of columns.

Behind the scenes, the Object Relational Designer is generating classes that represent the LINQ to SQL entities. You can view these classes by expanding the Store.dbml file and opening the Store.designer.cs or Store.designer.vb file.

Executing LINQ to SQL Queries After you create one or more LINQ to SQL entities by using the Object Relational Designer, you can start performing LINQ to SQL queries. You can write a LINQ to SQL query using either method syntax or query syntax. Let’s start with method syntax. Suppose that you want to retrieve a set of entities representing all of the rows from the Products database table. You can use the code in Listing 1.

Listing 1 Product.cs (method syntax).

using System;
using System.Linq;
using System.Data.Linq;
using System.Collections.Generic;
public partial class Product
{
public IEnumerable<product> Select()
{
StoreDataContext db = new StoreDataContext();
return db.Products;
}
}

The Select() method in Listing 1 returns all of the products from the Products database
table. The method consists of two lines of code. The first line of code instantiates
an instance of the StoreDataContext class. You created the StoreDataContext class
when you created the LINQ to SQL entities. Next, the Products property of this class
is used to return the products.

Notice that Listing 1 contains the definition for a class named Product and that this class is declared as a partial class. The other half of the partial class is contained in the Store.Designer.cs file that’s generated by the Object Relational Designer.

When using LINQ to SQL, you must be careful to import all of the necessary namespaces. You should always import the System.Linq and System.Data.Linq namespaces. If you don’t import these namespaces, the LINQ methods won’t be available.

If you want your data access code to resemble SQL code more closely, you can use query syntax instead of method syntax. The class in Listing 2 does the same thing as the class in Listing 1. However, this new class uses query syntax instead of method syntax.

Listing 2 Product.cs (query syntax).

using System;
using System.Linq;
using System.Data.Linq;
using System.Collections.Generic;
public partial class Product
{
public IEnumerable<product> Select()
{
StoreDataContext db = new StoreDataContext();
return from p in db.Products select p;
}
}

The class in Listing 2 is very similar to the previous class. The only difference
is that this new class uses the expression from p in db.Products select p to retrieve
the products. Whether you use method syntax or query syntax is entirely a matter
of personal preference. There’s no performance difference between the two methods.
If one type of syntax seems more natural to you, use it.
If you want to use either the class in Listing 1 or the class in Listing 2 to display
the products in an ASP.NET page, you can use an ObjectDataSource control to represent
the class. For example, the page in Listing 3 displays all of the products in a
GridView control by binding the GridView to an ObjectDataSource control that represents
the Product class.

Listing 3 ShowProducts.aspx.Listing 3 ShowProducts.aspx.

you view the page in Listing 3 in a web browser, you’ll see the rendered content contained in Figure 5.

It’s important to pause here for a moment in order to notice how simple LINQ to SQL makes accessing database data. You didn’t need to open a database connection or set up a command object. In fact, you didn’t write any ADO.NET or SQL code at all. LINQ to SQL reduced your data access code to its bare essentials.
Think of how much time you could save by taking advantage of LINQ to SQL when writing a database-driven web application!

Creating a Master/Detail Page with LINQ to SQL

The database query examined in the previous section was very simple; we just grabbed all of the rows from the table. But what if you need to perform a more complicated query? For example, how do you filter and order the results of a LINQ to SQL query in the same way as when performing a traditional SQL query? In this section, we’ll create a single-page master/detail form that illustrates how you can both filter and sort the results of a LINQ to SQL query.

  • The first step is to add a new database table to our project. I’m going to assume that the project contains a database table named Categories that looks like this:
    Column Name Column Type
    Id Int (identity, primary key)
    Name Nvarchar(50)
    The Categories table contains product category names such as Beverages, Meat, Cheese, and Other.
  • To create a relationship between the Categories and Products tables, add a new column to the Products table that associates each product with a category. The modified Products table looks like this:
    Column Name Column Type
    Id Int (identity, primary key)
    Name Nvarchar(50)
    Price Money
    CategoryId Int (NULL)
  • Next, we need to re-create the LINQ to SQL entities so that they correctly reflect the modified database objects. Start by opening the Store.dbml file in the Object Relational Designer by double-clicking the Store.dbml file in the Solution Explorer window.
  • Delete the Product entity from the Object Relational Designer so that you can start with a blank slate.
  • Drag both the Products and Categories database tables onto the Object Relational Designer from the Server Explorer/Database Explorer window.

After you complete these steps, the Object Relational Designer displays two entities corresponding to the Products and Categories table (see Figure 6).

Now that we’ve modified the database and updated the entities, we’re ready to write some code to retrieve the categories and products. The code in Listing 4 contains a partial class named Category that includes a method for retrieving all of the categories.
Listing 4 Category.cs.
using System;
using System.Linq;
using System.Data.Linq;
using System.Collections.Generic;
public partial class Category{
public IEnumerable<category> Select() {
StoreDataContext db = new StoreDataContext();
return from c in db.Categories select c;
}
}

There’s nothing new in the Category.cs class. The class contains a method named
Select() that uses LINQ to SQL query syntax to retrieve all of the categories from
the underlying Categories database table. Listing 5 contains a class for retrieving
products. This class contains a method named SelectByCategory() that retrieves products
matching a certain category. The products are returned in order of price.
Listing 5 Product.cs with SelectByCategory method.
    using System;
using System.Linq;
using System.Data.Linq;
using System.Collections.Generic;
public partial class Product{
public IEnumerable SelectByCategory(int categoryId) {
StoreDataContext db = new StoreDataContext();
return from p in db.Products where p.CategoryId == categoryId orderby p.Price select p;
}
}

The LINQ to SQL query in Listing 5 contains from, where, orderby, and select clauses. You should be familiar with these clauses from writing traditional SQL queries. The only weird thing is the order of these clauses. When writing LINQ to SQL queries, you must get used to adding the select clause at the end of the query rather than at the beginning of the query.

Finally, Listing 6 contains an ASP.NET page that takes advantage of both the Category and Product classes. The page displays a drop-down list of categories. When you select a category from the list, any matching products are displayed by a GridView control.

The page in Listing 6 enables you to select a category and display a list of matching products (see Figure 7). In other words, it contains a simple master/detail form.
Inserting Data with LINQ to SQL

In this final section, we’ll examine how you can use LINQ to SQL to modify database data. In this section, you’ll build a page that you can use to insert new records into the Products database table.

When using LINQ to SQL, you insert new records by calling the InsertOnSubmit() method. After calling the InsertOnSubmit() method, you must call SubmitChanges() to make the insertion happen. The SubmitChanges() method executes all of the database commands that have been queued. The modified Product class in Listing 7 illustrates how to write a method that inserts new products into the Products database table.

Listing 7 Product.cs with Insert method.

using System;
using System.Linq;
using System.Data.Linq;
using System.Collections.Generic;
public partial class Product{
public IEnumerable
Select() {
StoreDataContext db = new StoreDataContext();
return from p in db.Products select p;
}
public void Insert(Product newProduct) {
StoreDataContext db = new StoreDataContext();
db.Products.InsertOnSubmit(newProduct);
db.SubmitChanges();
}
}

The ASP.NET page in Listing 8 uses the Product class. The page contains a GridView
control and a FormView control. When you enter a new product with the FormView control,
the product is added to the database and displayed in the GridView (see Figure 8).

Listing 8 ShowInsert.aspx.

        <asp:formview id="Formview1" datasourceid="srcProducts" defaultmode="Insert" runat="server">
<InsertItemTemplate>
<asp:Label ID="lblName" Text="Name:" AssociatedControlID="txtName" runat="server" />
<br />
<asp:TextBox ID="txtName" Text='<%# Bind("Name") %>' runat="server" />
<br />
<br />
<asp:Label ID="lblPrice" Text="Price:" AssociatedControlID="txtPrice" runat="server" />
<br />
<asp:TextBox ID="txtPrice" Text='<%# Bind("Price") %>' runat="server" />
<br />
<br />
<asp:DropDownList ID="ddlCategories" DataSourceID="srcCategories" DataTextField="Name"
DataValueField="Id" AutoPostBack="true" runat="server" />
<asp:ObjectDataSource ID="srcCategories" TypeName="KannanTestApplication.LINQSamples.Category"
SelectMethod="Select" runat="server" />
<asp:Button ID="btnInsert" Text="Insert Product" CommandName="Insert" runat="server" />
</InsertItemTemplate>
</asp:formview>
<asp:gridview id="Gridview1" datasourceid="srcProducts" runat="server" />
<asp:objectdatasource id="srcProducts" typename="KannanTestApplication.LINQSamples.Product"
dataobjecttypename="KannanTestApplication.LINQSamples.Product" selectmethod="Select"
insertmethod="Insert" runat="server" />

To keep things simple, I’ve left out any validation from the page in Listing 8. In real life, at the very least, you would want to associate RequiredFieldValidator controls with both the txtName and txtPrice TextBox controls.
Notice how much code you avoid writing when using LINQ to SQL. You don’t need to get your hands dirty by touching any ADO.NET objects. You never need to set up a database connection or command. All of the low-level plumbing is handled for you in the background by LINQ to SQL.

Conclusion The purpose of this article was to provide a very brief introduction to using LINQ to SQL when building a database-driven ASP.NET application. My hope is that the sample code in this article has convinced you that using LINQ to SQL can dramatically reduce the amount of code you need to write when building
database-driven web applications

Happy Programming!!!