Tuesday, December 23, 2008

Solution to JavaScript File Include Problem From ASP.Net MasterPage

You can include javascript files using a simple script tag. However, you will soon discover that, when you are using this master page from content pages that are at different levels in folder hierarchy then the script files will be missing at some cases. This is due to the fact that, script file paths are referenced relative to the content page and NOT to the master page. As a result, despite having the correct include wrt the master page, your content pages may still miss the scripts!

The solution is simple. Add this following line (of course, replacing the sample values with your own ones) to your master page's page load method to add the script tag through code instead of through markup.

this.Page.ClientScript.RegisterClientScriptInclude("YourKey", ResolveUrl("~/Scripts/myscript.js");

Hope it saves you from the pain of adding a common js file into each of your content pages.

Asp.Net Membership: How to change a user's password from an admin account without knowing the current password?

Like mine, you may also need to change a user's password from an admin account. By default, when you are using ASP.Net authentication and storing the password in the hashed format, you will not be able to see the existing password in its decrypted form. Also, to change a password using the Membership API, you will need to know the existing password. However, here is a simple solution to the problem -

AspNetChangePassword

The idea is, you can reset the password of a user using the following code-

string tempPass = Membership.Provider.ResetPassword("username", string.Empty)

Make sure you have the config that allows you to change password without an answer to the security question. Now, you can invoke the ChangePassword method using this tempPass as the existing pass and your custom password as the new password. Refer to the following line for a compact implementation-

Membership.Provider.ChangePassword("username", Membership.Provider.ResetPassword("username", string.Empty), "custompass")

I believe this will save your time with a similar need.

Wednesday, November 26, 2008

Part 1: How am I IMPACTing following Scrum?

In a previous post in this blog, I introduced the nice little acronym IMPACT for agile. To recap, here is what IMPACT stands for -

"Iterative and Incremental development of a software by means of Merciless refactoring, Peer reviews, Automated acceptance testing, Continuous integration and of course, Test driven development"

To give you a little background around my story, let me tell you about a project that I am working since June 2006. The project is a micro-finance loan application automation server for the US financial industry. It acts as a mediator between a loan seeking customer and one of over 50 lenders in an attempt to get a loan for the customer. So, the server adds value by taking a single application to 50 odd lenders from a single submission unless no lender is left untried or some lender says 'yes' to it. This is done in real time, the processing time in average is less than 3 minutes.

Now that you have the background, let me introduce the the challenges associated with this project. The bullet points are-

  • Since this involves real dollars, there is nearly no margin for an error.
  • It processes more than a thousand loan applications per hour, so a high availability is a must.
  • This is done following agile Scrum and each two week one/two new lending partners need to be integrated.
  • The lending partners change their integration API from time to time and we need to accommodate the changes ASAP.

To address these challenges this is how we are responding-

Iterative and Incremental development (IID)

We are following Scrum and using ScrumPad to manage the IID. Basically, our clients/product owners put new requirements in terms of user stories in the product backlog at ScrumPad. So, with the prioritized product backlog we, the team, pick items to a sprint's backlog. Then as usual, we break it down to tasks and do everything that it takes to meet the deadline of two weeks. Within a sprint the following are the milestones-

Day 1 Day 2 Day 3 Day 4 Day 5 Day 6 Day 7 Day 8 Day 9 Day 10
Sprint Planning Dev & Test Dev & Test Dev & Test Dev & Test Dev & Test Dev & Test Dev & Test Test Release Production Release
  • 8th day - Sprint works are completed.
  • 9th day - Test delivery at a near production environment and feedback gathering from product owner.
  • 10th day - Incorporate feedbacks and release in production.

Note that, we generally produce a number of test releases within the first 8 days. That gives us an earlier chance to gather client feedbacks.

The beauty if this approach is, with this model in place we can release as early as in 8 working days, if not earlier. So, this helps us meeting the last two challenges as mentioned above.

Merciless refactoring

Developing incrementally offers much challenge in attaining the longevity of the product. Because, naturally as new features come in, we need to make room for that in the existing implementation.To ensure the quality and life of the product, we do merciless refactoring as we go. We have over 90% unit test coverage, which helps us in doing this continuous refactoring. So, the idea is-

  • Writing unit test and acceptance test.
  • Refactoring our code/design and validating against automated tests.

Peer reviews

This is probably the most important practice that I recommend. Because, as we had new members in the team, we found that the quality was somewhat degrading. Once, we started peer reviews, it was very helpful to the new comers as well as the veterans to keep the code quality up to the mark. We review the following things-

  • Naming of variables, methods, classes, files, namespaces etc.
  • Use of private methods for increased readability.
  • Hard coded string literals or constants.
  • Long/nested loops and long running if-else blocks.
  • Code commenting.
  • Quality of coding.

I would suggest you to try Microsoft's Stylecop, it will give you a great head start to ensure the first level code quality by enforcing the common rules. This practice is allowing us to continue the good quality over time.

I have always been shy of reading extra large text in the web. So, I thought I could better post this in two parts! I assure, next post will contain more images than texts, So, you better stay tuned for the next one...

Tuesday, November 18, 2008

Delving into client side capabilities of ASP.Net Ajax

I believe the client side scripting capabilities of ASP.Net Ajax is not utilized by many ASP.Net developers. This is most probably due to the fact that, not many people are aware of it at the first place. Also, since most of the javascripts are rendered secretly (read, not blatantly, which is good), most developers don't even feel the existence of the underlying javascript at all.

Two very simple examples of the client side library are given here as examples -

1. Did you know, if you have the following javascript method, it will be automatically called when your page's DOM is finished loading?

function pageLoad(sender, args) {
}


2. Do you know the following javascript code will add an event handler to catch whenever an asynchronous post back is completed?



Sys.WebForms.PageRequestManager.instance.add_endRequest(endRequestHandler)


These are just very little glimpses of the big scenario. To uncover more, visit the official MSDN documentation at http://msdn.microsoft.com/en-au/library/bb398822.aspx


If you are new to this, I assure, you will have a much better knowledge about ASP.Net Ajax scripting than ever before and can produce better quality javascript for your ASP.Net websites.


Happy digging!

IMPACTing for agile software development

Well, next time on a dev job interview when someone asks you the question, "Can you give us a brief idea on agile software development engineering practices?", you are probably gonna laugh on your mind and just answer, "IMPACT!". Yes, this is it, compact and right on target!

Today, I came up with this acronym about agile engineering practices and I think its a nice one :-)

IMPACT can be elaborated as follows-

I for Iterative and Incremental Development
M for Merciless Continuous Refactoring
P for Peer Code Reviews
A for Automated Acceptance Tests
C for Continuous Integration
T for Test Driven Development

For all you agile folks out there, I hope this IMPACT makes sense to you! I have found many people to take agile as a panacea and start getting skeptical as soon as they feel the heat in real life. Well, we all know, there is no free lunch! So, lets get our feet on track and do the first things first.

What are the first things? The answer is, IMPACT, if you really want to create a positive impact out of agile methods.

Comments are welcome!

Monday, November 10, 2008

RowTest Extension for NUnit

Well, I was just about to implement it myself! However, its good to see that the NUnit addin named RowTest actually allows us to do the data driven unit test through declarative programming and adding parameters to the dumb test methods!

http://www.andreas-schlapsi.com/projects/rowtest-extension-for-nunit/

Check out this website for an example and get started with RowTest.

Monday, November 03, 2008

Iterative and Incremental implementation of Code Reviews

Extreme Programming (XP) advocates for a pair-programming, taking the code review to its extreme. I have also found that pair programming generates a lot of speed and also helps producing better quality product in the first time. But, at the same time it's difficult to impress the management or prove return on investment associated with pair programming to the business people. So, what is the best possible solution? I believe, we can implement frequent peer code reviews to mimic the pair programming to some extent and get the benefit out of it.

In our team, we started implementing code reviews as we now recognize that there is no way to live without it. As usual, our approach is an iterative and incremental approach. So, we are taking small steps and eventually embracing the best practices in the team. I would like to share our plan here in this blog. The review process goes on the following work flow-

"When I am done with my work on task, I commit the code with the reviewer's name on the svn comment. CCNet automatically builds and sends a mail to the reviewer. The reviewer gets the review email through a filter and reviews the code and sends his feedback to me via IM/email."

Sprint #1: Review all the names or classes, files, methods, variables and so on. So, the reviewer emphasizes on the names and provides feedback on the following things-

1. Is the naming standard correctly followed?

2. Is this a meaningful identifier?

3. Does the name conform to the conventions used elsewhere in the code?

Sprint#2: Review the use of private methods and code structure. The to-do list is -

1. Would it make more sense to put some code into the private method for readability and/or reusability?

2. Is there any hard-coded constant directly used without referring to a const/readonly data type?

3. For all the methods, is it possible to reduce the dependency by using a simple parameter instead of a whole object?

4. Learn from sprint#1 and use the common learning.

Sprint#3: Review the use of loops, if-else blocks. At this iteration, the to-do is-

1. Is it possible to eliminate a loop?

2. Is it possible to avoid the nested loops?

3. Is there a large if-else-if-else block? Why is it required? Is this large conditional block a possible candidate for future change?

4. Learn from sprint#2 and use the common learning.

Well, this is pretty much it. The idea is, we feel its not practical to go with an overnight policy for implementing peer code reviews. But, its very much possible that we do it in small increments and at each sprint's retrospective we bring this point. So, we are all informed that we need to do reviews, which, eventually should sustain as a best practice!

If you think you have some ideas regarding this, please share it with me/my readers.

Saturday, September 06, 2008

CruiseControl.Net (CCNet) configuration example for NCover

CruiseControl.Net is a great continuous integration tool for .Net projects. It not only continuously builds your software but provides some really helpful reports to monitor your project's progress.

In agile world, we all speak of self-testing code or test driven development (TDD). If we really want to ensure our code has enough test coverage, we need to use some tool to ease our lives and NCover is a good one for this purpose. To learn more about NCover, please visit this.

When integrating to CCNet, you can use a similar configuration in ccnet.config as shown below to show NCover reports for your project-

\par ?? <\cf3 msbuild\cf1 >\par ?? <\cf3 executable\cf1 >\cf0 C:\\WINDOWS\\Microsoft.NET\\Framework\\v3.5\\MSBuild.exe\cf1 \par ?? <\cf3 projectFile\cf1 >\cf0 CISample.sln\cf1 \par ?? <\cf3 buildArgs\cf1 >\cf0 /p:Configuration=Debug\cf1 \par ?? <\cf3 targets\cf1 >\cf0 Rebuild\cf1 \par ?? <\cf3 timeout\cf1 >\cf0 300\cf1 \par ?? <\cf3 logger\cf1 >\cf0 C:\\Program Files\\CruiseControl.NET\\server\\ThoughtWorks.CruiseControl.MsBuild.dll\cf1 \par ?? \par ??\par ?? \par ?? <\cf3 nunit\cf1 >\par ?? <\cf3 path\cf1 >\cf0 C:\\Program Files\\NUnit 2.4.1\\bin\\nunit-console.exe\cf1 \par ?? <\cf3 assemblies\cf1 >\par ?? <\cf3 assembly\cf1 >\cf0 CISample\\bin\\Debug\\CISample.dll\cf1 \par ?? \par ?? \par ??\par ?? \par ?? <\cf3 exec\cf1 >\par ?? <\cf3 executable\cf1 >\cf0 ncover.console.exe\cf1 \par ?? <\cf3 baseDirectory\cf1 >\cf0 CISample\\bin\\Debug\\\cf1 \par ?? <\cf3 buildArgs\cf1 >\cf0 nunit-console CISample.dll //xml coverage.xml //ea NUnit.Framework.TestFixtureAttribute\cf1 \par ?? \par ??\par ?? \par ?? <\cf3 exec\cf1 >\par ?? <\cf3 executable\cf1 >\cf0 NCoverExplorer.Console.exe\cf1 \par ?? <\cf3 baseDirectory\cf1 >\cf0 CISample\\bin\\Debug\\\cf1 \par ?? <\cf3 buildArgs\cf1 >\cf0 coverage.xml /xml /r:ModuleMethodFunctionSummary\cf1 \par ?? \par ??\par ?? } -->

10 <tasks>

11 <!-- Task for MSBuild -->

12 <msbuild>

13 <executable>C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe</executable>

14 <projectFile>CISample.sln</projectFile>

15 <buildArgs>/p:Configuration=Debug</buildArgs>

16 <targets>Rebuild</targets>

17 <timeout>300</timeout>

18 <logger>C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>

19 </msbuild>

20

21 <!-- Task for NUnit -->

22 <nunit>

23 <path>C:\Program Files\NUnit 2.4.1\bin\nunit-console.exe</path>

24 <assemblies>

25 <assembly>CISample\bin\Debug\CISample.dll</assembly>

26 </assemblies>

27 </nunit>

28

29 <!-- Task for NCover -->

30 <exec>

31 <executable>ncover.console.exe</executable>

32 <baseDirectory>CISample\bin\Debug\</baseDirectory>

33 <buildArgs>nunit-console CISample.dll //xml coverage.xml //ea NUnit.Framework.TestFixtureAttribute</buildArgs>

34 </exec>

35

36 <!-- Task for NCoverExplorer -->

37 <exec>

38 <executable>NCoverExplorer.Console.exe</executable>

39 <baseDirectory>CISample\bin\Debug\</baseDirectory>

40 <buildArgs>coverage.xml /xml /r:ModuleMethodFunctionSummary</buildArgs>

41 </exec>

42

43 </tasks>

You see that there are two NCover related <exec> nodes. The first one generates the coverage.xml. Then using this first one you can create actual report to present specifying the desired level of details of the report.

Monday, September 01, 2008

Set and Compile using C# Language Version 2.0 in Visual Studio 2008

I know, while most of you are very happy with the new features in Visual Studio 2008, its sad that not all your deployment environments are upgraded to .Net framework 3.5. I had a similar situation as well on one of my projects.

Its great that you can just navigate to a VS 2008 project file properties and from the Application Tab select the Target .Net Framework version to use one of .Net 2.0, 3.0 and 3.5. But this doesn't solve all the problems. You will soon discover that, your application doesn't show an error when you write C# 3.0 code with the target framework set to 2.0. This is because, the IDE by default uses the latest language version by default.

To solve this problem, Navigate to project properties > Build > Advanced > Language Version and choose ISO-2 (or ISO-1). Now with this information, the VS 2008 will start showing compiler errors for features that don't comply to the version specification!

BDD - My First BDD Code using RSpec in Ruby

I am really really happy to see people putting so much efforts for building high quality, nearly all avoidable error free software. I am a big believer of Test Driven Development and doing TDD for about two years now. I have always had the feeling that TDD is a kind of a misnomer because to some people the term 'Test' refers to finding bugs. For this very reason, when people gets started with TDD, they consider it as a waste of time to write so much extra code that doesn't necessarily find bugs!

Well, a good vocabulary always makes it more attractive and useful. Now with BDD, Behavior Driven Development, I think the vocabulary that people actually codes the behaviors and implements the behaviors, not the tests, makes it more like it.

So, lets see my first ever written RSpec ruby code and the sexy html output!

#This is a poor Stack implementation

class Stack
def initialize
@items = []
end
def push(item)
@items << item
end
def pop
return nil unless @items && @items.length > 0
item = @items.last
@items.delete item
return item
end
def peek
return nil unless @items && @items.length > 0
@items.last
end
def empty?
@items.empty?
end
end

#This is the RSpec ruby code. Isn't is Simple?

describe Stack do
before(:each) do
@stack = Stack.new
end
describe "Empty" do
it "Should be empty when created" do
@stack.empty?.should == true
end
end
describe "With One Item (value = 3)" do
before(:each) do
@stack.push(3)
end
it "should not be empty" do
@stack.empty?.should be_false
end
it "should return the item (=3) when #peek" do
@stack.peek.should == 3
end
it "should return the item (=3) when #pop" do
@stack.pop.should == 3
end
end
end

Well, we all write codes and are doing this day and night for years. What I like to see is as sexy an output as the following from my source code :-)

RSpec

I know, you liked the output. For more you may check at http://rspec.info/

Need a similar solution on .Net? Keep Googling and come back to me if you see a good BDD tool. I would really like to use BDD in my .Net projects and see how better it performs over TDD.

Wednesday, August 20, 2008

My Target items still in the 2008 learning Queue

1. Windows Workflow foundation.

2. Study about ERP and take a good look into a popular open-source ERP application.

3. Study on SOA.

4. Study on Smart Client applications.

Wednesday, August 13, 2008

Unit Testing using Mocks - FillWithMocks, Fill all or only selected properties with Mocks using only a single method call

I have been doing TDD for about two years now and using mock testing for interaction based unit testing in my projects. What I have learned over this time is, a unit testable design leads to introduction of interfaces and dependency injection for testing a code in isolation. And when I want to perform tests on my interactions, I need to create mock objects and inject these mock instances to my object under test. Sometimes, a unit test class needs to create quite a few of such mock objects and I feel this can be done using a simple wrapper around the usual mocking frameworks.

I suggest a similar and even more powerful wrapper so that you don't need to create instances for each of the mock objects, rather do it in a single call for all your desired mocks. I have shown this method for NMock2, however, its evident that you can write your own method for your favorite mocking framework just using this code as a reference.

This code is written in C# 3.0 and should compile in .Net 3.5. You will need to add a reference to NMock2 to compile this. Also, you need to know a bit about Reflection to understand the following code fragment.

Disclaimer: This code is just a simple example and it may not suit all your needs.

1 using System;

2 using System.Collections.Generic;

3 using System.Linq;

4 using System.Text;

5 using System.Reflection;

6

7

8 namespace NMock2.Extensions

9 {

10 public static class MockeryExtensions

11 {

12 /// <summary>

13 /// This method will fill all properties of the 'target' of interface type having a setter

14 /// </summary>

15 /// <param name="mocks"></param>

16 /// <param name="target"></param>

17 public static void FillWithMocks(this Mockery mocks, object target)

18 {

19 Type targetType = target.GetType();

20 PropertyInfo []properties = target.GetType().GetProperties();

21

22 foreach (PropertyInfo property in properties)

23 {

24 Type ptype = property.PropertyType;

25 if (ptype.IsInterface)

26 {

27 if(targetType.GetMethod(string.Format("set_{0}", property.Name)) != null)

28 {

29 targetType.GetProperty(property.Name).SetValue(target, mocks.NewMock(ptype), new object[] { });

30 }

31 }

32 }

33 }

34

35 /// <summary>

36 /// This method will fill the properties with names specified in the propertyNames array having a setter

37 /// </summary>

38 /// <param name="mocks"></param>

39 /// <param name="target"></param>

40 /// <param name="propertyNames"></param>

41 public static void FillWithMocks(this Mockery mocks, object target, params string[] propertyNames)

42 {

43 Type targetType = target.GetType();

44 foreach (string propertyName in propertyNames)

45 {

46 PropertyInfo pInfo = targetType.GetProperty(propertyName);

47 if (pInfo != null && targetType.GetMethod(string.Format("set_{0}", propertyName)) != null)

48 {

49 pInfo.SetValue(target, mocks.NewMock(pInfo.PropertyType), null);

50 }

51 else

52 {

53 throw new ArgumentException(string.Format("the property {0} is not found or does not have a setter", pInfo.Name));

54 }

55 }

56 }

57 }

58 }

So, with this extension method in place, you can go and write your test code in a much compact manner. The following is an example showing one possible use of this method in your NUnit test code.

83 public interface IMyInterface

84 {

85 void MyMethod(string name);

86 }

87

88 public class MyExampleClass

89 {

90 public IMyInterface MyPropertyOne

91 {

92 get;

93 set;

94 }

95

96 public IMyInterface MyPropertyTwo

97 {

98 get;

99 set;

100 }

101

102 public IMyInterface MyPropertyThree

103 {

104 get;

105 set;

106 }

107

108 public MyExampleClass()

109 {

110

111 }

112 }

113

114 [TestFixture]

115 public class MyExampleClassTest

116 {

117 private MyExampleClass _myExampleClass;

118 private Mockery _mocks;

119

120 [SetUp]

121 public void Init()

122 {

123 _myExampleClass = new MyExampleClass();

124 _mocks = new Mockery();

125

126 //This call fills all the three properties with mocks

127 _mocks.FillWithMocks(_myExampleClass);

128

129 //This call fills only MyPropertyOne and MyPropertyTwo with mocks

130 _mocks.FillWithMocks(_myExampleClass, "MyPropertyOne", "MyPropertyTwo");

131 }

132 }

Comments are welcome!

Tuesday, August 12, 2008

XDocument.ToStringWithXmlDeclaration() - Get the string representation of XDcoument with its Xml Declaration

The System.Xml.Linq.XDocument.ToString() produces a serialized string version of the XDocument object. But unfortunately, while doing so, it leaves the xml declaration in the serialized version which may be required in your application.

Again, there is another method called Save that produces the serialized version including xml declaration. So, I think we can write a simple extension method for producing the xml declaration as shown in the following -

14 class Program

15 {

16 static void Main(string[] args)

17 {

18

19 XDocument doc = new XDocument(new XDeclaration("1.0", "utf-8", null), new XElement("root"));

20 Console.WriteLine(doc.ToStringWithXmlDeclaration());

21 }

22 }

23

24

25 public static class XDocumentExtensions

26 {

27 public static string ToStringWithXmlDeclaration(this XDocument doc)

28 {

29 StringBuilder builder = new StringBuilder();

30 StringWriter writer = new StringWriter(builder);

31 doc.Save(writer);

32 writer.Flush();

33 return builder.ToString();

34 }

35 }

Apart from its purpose, this is also an example use of the Extension Method feature of C# 3.0.

Monday, August 11, 2008

Simple Wildcard replacement on the Rendered Html of Asp.Net Page

This is a simple solution for implementing wildcard replacements in your asp.net pages. You may use this, if you want to replace some tokens / merge codes in the asp.net generated html by your personalized values.

System.Web.UI.Control has a virtual method called 'Render' of the following signature -

protected internal virtual void Render(
HtmlTextWriter writer
)

Since, all your ASP.Net pages and server controls are subclasses of this Control class, you can override this method and manipulate the html that's rendered from this control. So, using this method, we will intercept the render method and apply a global replacement on the tokens present in the generated html. The C# code looks like the following one -

21 protected override void Render(HtmlTextWriter writer)

22 {

24 MemoryStream stream = new MemoryStream();

25 StreamWriter memWriter = new StreamWriter(stream);

26 HtmlTextWriter myWriter = new HtmlTextWriter(memWriter);

27

28 base.Render(myWriter);

29 myWriter.Flush();

30

31 stream.Position = 0;

32

33 string renderedHtml = new StreamReader(stream).ReadToEnd();

34

35 renderedHtml = renderedHtml.Replace("$Name$", "Sohan");

36

37 writer.Write(renderedHtml);

38 writer.Close();

39 myWriter.Close();

40 stream.Close();

41 }

So, the steps are -

1. Intercept the rendering - override the Render method.

2. Get the generated html - invoke the Render method on the base class supplying it a simple memory stream writer. Then read the html from the stream. You can also make use of other TextWriter implementations including StringWriter.

3. Apply your replacements - use simple string.Replace or Regex.Replace for more control.

4. Now, write the replaced content on the original writer.

Hope it helps!

Thursday, August 07, 2008

Log4Net SmtpAppender and sending emails with log messages

Since my client asked me if it was possible to generate emails for log entries on an error/fatal level I took a look into the Log4Net SmtpAppender. In your project you may need to implement a similar function and in that case you may use a log4net configuration like the following one-

93 <appender name="SmtpAppender" type="log4net.Appender.SmtpAppender">

94 <to value="" />

95 <from value="" />

96 <Username value=""></Username>

97 <password value="" ></password>

98 <authentication value="Basic"></authentication>

99 <subject value="test logging message from log4net" />

100 <smtpHost value="" />

101 <bufferSize value="512" />

102 <lossy value="true" />

103 <evaluator type="log4net.Core.LevelEvaluator">

104 <threshold value="INFO"/>

105 </evaluator>

106 <layout type="log4net.Layout.PatternLayout">

107 <conversionPattern value="%newline%date [%thread] %-5level %logger [%property{NDC}] - %message%newline%newline%newline" />

108 </layout>

109 </appender>

110

111 <root>

112 <level value="DEBUG"/>

113 <appender-ref ref="LogFileAppender"/>

114 <appender-ref ref="SmtpAppender"/>

115 </root>

I had to use the username and password as my server requires authentication. Now, in case your server don't demand authentication, you can avoid using these two nodes as well as the authentication node. You can also specify the port name if your smtp server is not using the default port.

Doing so keeps you posted of the error conditions early since sometimes finding an error entry by periodically checking is missed. Hope this helps someone with similar need.

Tuesday, August 05, 2008

Comparing with NULL in where clause using Linq to SQL

In SQL Server, a SQL statement like 'NULL=NULL' evaluates to false. however 'NULL IS NULL' evaluates to true. So, for NULL values in your database columns, you need to use the 'IS' operator instead of the regular '=' operator.

The problem is, in Linq to SQL, there is no such 'IS' operator since 'IS' is already used as a C# language keyword. So, when you are invoking an equality check in your Linq to SQL where clause to a nullable column you need to be alert on this behavior.

For example, take the following sample code that I wrote to demonstrate this topic.

1 using System;

2 using System.Collections.Generic;

3 using System.Linq;

4 using System.Text;

5 using System.IO;

6

7 namespace ConsoleApplication1

8 {

9 class Program

10 {

11 static void Main(string[] args)

12 {

13 MyDataContext context = new MyDataContext();

14 context.Log = new ConsoleWriter();

15

16 string name = null;

17 var aff = from a in context.Affiliates

18 where

19 a.CompanyName == name

20 select a.ID;

21 var aff2 = from a in context.Affiliates where a.CompanyName == null select a.ID;

22

23 aff.ToList();

24 aff2.ToList();

25 }

26 }

27

28 class ConsoleWriter : TextWriter

29 {

30

31 public override Encoding Encoding

32 {

33 get { return Encoding.UTF8; }

34 }

35

36 public override void Write(string value)

37 {

38 base.Write(value);

39 Console.WriteLine(value);

40 }

41

42 public override void Write(char[] buffer, int index, int count)

43 {

44 base.Write(buffer, index, count);

45 Console.WriteLine(buffer, index, count);

46 }

47 }

48 }

In this code, I have attached a sample logger to my DataContext so that all my queries are logged. Now I ran two queries. Lets take a look at the first query and its logger output,

16 string name = null;

17 var aff = from a in context.Affiliates

18 where

19 a.CompanyName == name

20 select a.ID;

The logger output after executing this query is, as follows -

SELECT [t0].[ID]
FROM [dbo].[Affiliates] AS [t0]
WHERE [t0].[CompanyName] = @p0

-- @p0: Input VarChar (Size = 0; Prec = 0; Scale = 0) [Null]

So, you see that although a null is assigned in the variable 'name', the Linq to SQL generated query uses the '=' operator which may lead to undesired results.

However, the second query and its logger output looks like the following -

21 var aff2 = from a in context.Affiliates where a.CompanyName == null select a.ID;

SELECT [t0].[ID]
FROM [dbo].[Affiliates] AS [t0]
WHERE [t0].[CompanyName] IS NULL

Here, the generated query uses the 'IS' operator which is desirable.

In case, you want Linq to SQL to generate the first code using 'IS' operator, you may use something like the following one -

26 var aff3 = from a in context.Affiliates

27 where

28 ((name == null && a.CompanyName == null) || (a.CompanyName == name))

29 select a.ID;

This query produces the following SQL code -

SELECT [t0].[ID]
FROM [dbo].[Affiliates] AS [t0]
WHERE ([t0].[CompanyName] IS NULL) OR ([t0].[CompanyName] = @p0)

So, to end, whenever you are writing a where clause on a nullable column using Linq to SQL, make sure you know the consequences and take measures accordingly.

Happy coding!

Monday, August 04, 2008

JQuery - I will consider using it in my future web project

I find the problems with cross-browser issues with Javascript to be bothering at times. Also, I am most annoyed with Javascript because, with Javascript, I need to think about another programming language along with my server side programming. I have a feeling that Javascript codes make the web application harder to test using various automated test frameworks and adds complexities as there are different browsers who interpret the Javascript code in different ways.

As I have always preferred to write only as few lines of Javascript as I can, I found JQuery to be an interesting choice. I have just taken a look into the documentation and wish to use it in a future project.

One thing about JQuery is, the code looks a little hard to read to me in some cases. The use of anonymous methods and callbacks should be standardized and I suggest, its better to write and refer to actual methods instead of the unreadable anonymous methods all around.

You may wish and take a look at JQuery at http://www.JQuery.com for more!

Sunday, August 03, 2008

Ninject - Dependency Injection Framework for .Net Objects

I loved Ninject because

- I don't love to write/edit XML documents myself.

- I think Ninject can save a lot of coding and debugging time.

- This is a cool framework :-) with a fun-to-read documentation.

- It uses simple conventions and Attributes for resolving most dependencies behind the scene.

- You can take full advantage to lambda expressions for writing compact codes.

Today, I took a look into this Ninject framework. I have used Spring.Net and Unity in my previous and current projects. But seems like Ninject has the most 'fluent vocabulary' that lets you develop on most 'fluent interfaces'.

Take a look at the fun-to-read documentation at http://dojo.ninject.org/wiki/display/NINJECT/Home and enjoy the 20 minutes while you eat the whole document!