Friday, January 12, 2007

The "as" operator as described in MSDN is an operator: "Used to perform conversions between compatible reference types". We have to keep this in mind when coding. Often it is just easier (and it looks nicer too) to use an "as" operator instead of a cast, or when we want to handle the DBNull value returned from the database like in the following scenario:

string s = reader["Name"] as string;

instead of

string s = (string)((reader["Name"] is DBnull) ? null : reader["Name"]);

Assuming that the name column can be null in the database.

When we use it we accept that something could be of incompatible type such as Name column being of numeric type return. What happens then? What happens if the column type has changed? In the scenario above, we will always get a null reference, which in a worst case scenario we will discover very late in project.

Of course in some situations it is just what we need. What I have found however is that misusing the "as" operator can often lead to unexpected NullReferrenceException exceptions being thrown (or worse yet nothing wrong happens at first). If you find that happening it may mean that you are using "as" operator as a shortcut where an ordinary cast would be in place. Using a cast often causes bugs to appear sooner in the development life cycle which is always a nice thing. So basically a rule of thumb is to always think twice whether to use a cast or an "as" operator.

kick it on DotNetKicks.com

Friday, January 12, 2007 12:17:26 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [3]  | 

Since the beginning of my adventure with .NET I have always asked myself one question: why do we need the DBNull type? Is a simple null reference not enough?
MSDN says that DBNull "Represents a nonexistent value". From a logical point of view - this one sentence explains why a null reference cannot be used - because it is a null reference and not a lack of value. But is it enough to introduce a type that causes a lot of trouble?

DBNull is typically used in ADO.NET when returning data from the database. If one column does not have a value in the database, it will be represented as a DBNull object. That is something altogether different from what I would expect at the domain level. When working with objects when there is a Client object, and I ask for his Name then if the name is not there I expect to get null in return. It is very natural to me and probably to most of the developers. When we need to interact with data layer that is where most of the problems with DBNull kick in.

Consider a simple example of a Client's Name property which is of a String type. In your code you accept a situation when the Name is null which may mean that it has never been set. When you save such a Client to a database using a simple Insert call, everything works OK. (it was in fact my data access library that handled null inserts by changing them to DBNulls) You check the database and the data is in fact there and the Name is "null". When next time you try to get the Client from the database, you have to read all the columns and put the values into your object like in the following example:

Client c = new Client();
c.Id = (Guid)row["Id"];
c.Name = (string)row["Name"];
...

This will result in an InvalidCastException exception being thrown with a message "Unable to cast object of type 'System.DBNull' to type 'System.String'." That is of course because null values from the database are represented as DBNull objects.

Typical solution for this problem is to check the column for DBNull before casting or using an "as" operator which you have to be carefull with as I describe in another post.

Whichever way you choose, what you get is an overly complicated code that does a simple thing!

I don't think that the sentence from MSDN that describes the purpose of DBNull is a good excuse for introducing DBNull type. I don't think that returning null instead of DBNull would cause any loss of information. What I think is that DBNull should have never been introduced because it makes developer's work harder without adding any real value. Additionally ADO.NET is inconsistent in that it allows saving a null referrence to a database but does return DBNull instead. Because of the fact that I don't like to deal with DBNulls, in my data access library, I'm always replacing it with a null reference so I never get it to propagate to the upper layers. That way I get a better separation from a database level stuff.

BTW: If anyone has something to say in defense of the DBNull I woulreferenced gladly hear it.

kick it on DotNetKicks.com

Friday, January 12, 2007 12:08:55 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [8]  | 
 Thursday, January 11, 2007

It is a common practice in ASP.NET development to use controls provided by third parties. Such controls are usually distributed in form of an assmebly .dll files which you put into the Bin folder of your ASP.NET application. When using Visual Studio, you just add a reference to a file and the file is copied to that directory for you. What you don't get are new icons on the Toolbox representing newly added controls. You have to have to go to the Toolbox, select Choose Items... from context menu and point to the same dll file you have just used when adding a reference.

A much easier way to accomplish the same thing is to just do this second step though. By adding items to a Toolbox, Visual Studio automatically copies the required files into the Bin folder and by doing so, creates a reference to it so you don't have to.

When adding adding items to the Toolbox I usually prefer to create a separate Tab and add items there. For each group of controls I create a new Tab. The reason for this is that it is much easier to remove a whole Tab from the Toolbox than each individual item at a time. (You can also use the Choose Items... window to remove unneeded items, but I have found removing the Tab a lot easier and faster).

The third and in my opinion the best way of adding third party controls to a project is to create a separate project in the solution. In this project, for each control you want in your Toolbox, create a class and inherit it from this control. I have found that Visual Studio 2005 automatically adds to the Toolbox, controls that it finds in the Solution. An advantage of such an approach (other than that it is generally a good idea to always do so) is that now you can go and reset the Toolbox and your controls will still be there - after Visual Studio decides it is time :-) which usually happens when switching from html/aspx view do design view.

kick it on DotNetKicks.com

Thursday, January 11, 2007 11:58:42 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 
 Thursday, January 04, 2007

There is a very useful class in the .NET framework that allows you to cancel an event from the handler perspective. This class is the CancelEventArgs. Typically using this class looks as follows:

event EventHandler<CancelEventArgs> Click;
void OnClick()
{
    CancelEventArgs e = new CancelEventArgs();
    Click(this, e);
    if (e.Cancel)
    {
        // do nothing
    }
    else
    {
        // do something
    }
}

void ClickHandler(object sender, CancelEventArgs e)
{
    if (something)
    {
        e.Cancel = true;
    }
}

BTW: I have no idea why Microsoft defined CancelEventArgs under System.ComponentModel namespace.

Simple and easy. But there is a problem. What if there was a second handler for the Click event?

void ClickHandler2(object sender, CancelEventArgs e)
{
    e.Cancel = !IsValid();
}

In some scenarios, the ClickHandler2 would override changes made by ClickHandler - i.e. it would set Cancel property to false in case the state was Valid. I strongly discourage you from ever setting Cancel property to false! The problem is that in the handler method you never know if you are the only one handler or are there more handlers involved! If a previous handler had already cancelled the event you will lose this information!

In order to prevent potential mistakes, I propose an alternative version of CancelEventArgs. The version that will prevent you from making a mistake. Below is a how such a class could look like:

class CancelEventArgs : EventArgs
{
    bool cancelled;
    public bool Cancelled
    {
        get { return cancelled; }
    }
    public void Cancel()
    {
        cancelled = true;
    }
}

Notice that the Cancel property is now called Cancelled and is read-only. To Cancel an event you use the Cancel method which works only one way - there is no way to accidentally set Cancelled to false. The safer, the better :-)

kick it on DotNetKicks.com

Thursday, January 04, 2007 10:34:37 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [4]  | 
 Thursday, December 21, 2006

I have found a post on Web Development Team's blog providing SOME information on what was changed/fixed with the new Service Pack. There is also another post on Scott Guthrie's blog on the same topic. Good!

But wait! Am I really expected to look all over the Internet and gather pieces of information just to build a list that SHOULD be available in a KNOWN and EASILY ACCESSIBLE location? You got to be kidding!

Thursday, December 21, 2006 8:33:04 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

For some time now I have been having problems with "Connect To Server" window of Microsoft SQL Server Management Studio. The standard problem is that has problems remembering the password, or rather it has a habit of forgetting. The effect is that each time I run the MSSMS, there is a chance that my password will not be there even if I have checked the check box to remember it before. I'm currently running Windows 2003 Server, but I had exact the same problem on Windows XP.

Over a time I've got used to it and I no longer bother to check the "Remember Password" check box. Today however I have began to have a new suspicion.

Almost every time I try to log in to the server for the first time, I get a message that login or password was incorrect. I have always reentered my password thinking that I had made a typo. Some times it took me three times to get it right and that made me think.

Why is that window different? When I use the same password for other windows, my success/error rate is almost zero. Here I'm far from that. So I've investigated the issue.

The goal was simple: after entering a user name and password and getting a failed login attempt saying that the user name or password was incorrect, check if the message is right. Options were just to retry without changing anything or compare the entered text with what should be entered.

The first method was too easy :-). So I have decided to see what's in there. User name was a plain text so it was easy. And since it IS remembered, I have confirmed no error there. As for the password. I have used the Runtime Object Editor, to look under the hood. And guess what? Password was also correct!

Given the investigation I can say with certainty that there is a bug in the MS SMS! Such a simple function and it doesn't work!!! I have found one similar bug report. Not exactly the same but I think it is somehow connected. Imagine that. Big company, lots of money, lots of time, one small window and so many bugs!

kick it on DotNetKicks.com

Thursday, December 21, 2006 12:41:53 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [6]  | 
 Tuesday, December 19, 2006

Now I have a brand new Visual Studio 2005 Service Pack 1 installed. I'm happy with it, but I would be even more happy if I knew what was fixed by the installation. And so I went searching.

After a while, I just gave up! It is just to hard for me to accomplish the task of finding some kind of change log for the Service Pack 1! What I have found were Visual Studio 2005 Service Pack 1 release notes. On this page hidden in the summary section, just before a list of requirements and a very long list of installation issues, there it was, the link to What’s New in Visual Studio 2005 SP1. I have followed the link.

On the destination page one thing caught my attention - the topic: "What's New in Visual Studio 2005, This topic has been updated for Visual Studio 2005 SP1". Scrolling down a little, confirmed my suspicions. It is not a list of new features or bug fixes that were distributed with the new Service Pack 1. It is an overview of features the Visual Studio has now, after you install SP1. More Over! Look at the "New in Visual Studio 2005 SP1" section!!! Its empty.

I don't suppose that Microsoft is so evil not to provide some kind of change log. I only know that they just cannot make their own website usable and put the interesting things somewhere where people can actually find them. So, if anyone knows where can I get the list of features introduced with the new SP1 and the list of bug fixed, I would be grateful if he shares the knowledge.

kick it on DotNetKicks.com

Tuesday, December 19, 2006 7:52:33 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

One more time Microsoft has proven that they just cannot do things right. This time it's all about the newly released Service Pack 1 for Visual Studio 2005.

I'm certain that most of the developers working with Visual Studio 2005 know about the fact that the Service Pack has just been released. If not, at least they are aware of the fact that Microsoft was planning to release the product for some time now. So now it has been released. Are you ready to install it? Try! I have tried and it was not an easy task!

When first I have read that it is available I didn't think long before I went to the www.microsoft.com site. There I have used the search function in hope ... I don't even know what I had hoped for, given my previous experiences with searching Microsoft's site using Microsoft's search engine. The search results were disappointing yet not surprising - couldn't find it:


I have even tried to exclude the "beta" word, but with no better effect:

So, as usual, when I need to find something on Microsoft's site, I used Google (!!!). No surprise here, first result - a hit:

Having the page I went downloading. After starting the download I was presented with a funny page telling me that people who have downloaded Visual Studio 2005 Service Pack 1 have also downloaded ... Visual Studio 2005 Service Pack 1. What a coincidence :-)

After few hours of download (it has 450MB) I could finally run the setup and wait for few hours (or so according to the information on Microsoft's page) until it installs .

I had the setup procedure up and running and. Oh no! They have worked too long on this product to just let it install in like that! After a couple of minutes of waiting I've been presented with an error message Error 1718 some file did not pass the digital signature check:

What's going on? I'm sure most of us don't bother to read the installation procedure on the download page, especially as it is presented below download button, after clicking which you are redirected to another page, but there there is an information that such a problem may occur. Unfortunately, until you try installing SP1 on your concrete system, you don't know if you need to follow the procedure and by that time you have already lost a dozen of minutes. After pressing OK - the only available option, the Setup Procedure went through the same steps as before - i.e.: I had to agree to the same license terms etc. This time though it took more than ten times the amount of time just to inform me about the same problem once more!

After following the procedure I was finally able to install the service pack, after wasting a lot of time on it.

BTW: Since I haven't changed anything in my default Windows 2003 installation it seams to me that many people will have the same problem with the new Service Pack as I had!
If I count the time I have spent on trying to install the Service Pack and multiply this by the number of people that might have the problem I get a rather big number. Who is responsible? (Again! Last time it was because of IE7 that many people lost a lot of time because of the problems installing it and yet more (all) suffered from incredibly long installation time not to count few restarts and 2 validations during the process).

The question remains: why Microsoft, given all its resources, can't make it right the first time? (or second for that matter). Why they have to have everything so tightly integrated in to the operating system (like IE)? It is like if I had a house and my TV was integrated with it!

kick it on DotNetKicks.com

Tuesday, December 19, 2006 7:39:58 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 
 Thursday, December 07, 2006

In my recent article on Immediate Window, I have showed how you can use it to debug your application, but also how to run arbitrary code. Working with Immediate Window has one major drawback: it requires a lot of typing without any kind of support from the IDE. There is however an alternative way to call your methods using Visual Studio: Object Test Bench.

Object Test Bench as the name suggests is used to test objects. It has a simple visual interface that makes it easier to work with than with Immediate Window. For example if we have a class:

public class SomeType
{
  public string SomeMethod()
  {
    return "return value"
  }
}

Then we can add an instance of this class to the Object Test Bench, and execute any of its methods using context menu as on the picture below:

 

If method that is to be invoked requires parameters, Visual Studio will display a special dialog box where you can enter appropriate values - or select them from the list of other objects if necessary. Also, if the method has a return value, the result will be added to the Object Test Bench as a new object on which you can also invoke methods.

To use the Object Test Bench, go to the Class View (ctrl+shift+c), navigate to a class you want to test and from the context menu, select "Create Instance" or "Invoke Static Method" depending on what you are trying to test. You can also access the same functionality through the Class Designer (Class Diagram).

As good as the Object Test Bench may appear to be, there are also some major problems with it that in practice make it useless - at least for me.

The first and most serious problem that disqualifies the bench is the fact that any time you make a change in the code, the whole object structure is deleted from the bench. Just imagine spending couple of minutes setting objects up just to find out that one of the method requires changes. After you make the change, you have to set the whole bench from the beginning. Immediate Window does suffer from the same problem, but it is a lot easier to just run the same command sequence by pressing UP or DOWN arrows. You cannot do this in the Object Test Bench.

The second problem is that the Object Test Bench is only accessible through the Class Diagram - which I don't use and through the Class View - which I also don't use - I only work with Solution Explorer. It may not be big problem, but it requires an additional step to use the feature. Compare this to almost immediate access to Immediate Window and multiply by the number of times you use the feature.

Third problem is that you may not see the Object Test Bench at all! Some times it happens, that when you try to "Create Instance" of an object either through Class Diagram or Class View, there is no such function in the context menu! (BTW: Visual Studio is known to hide its features randomly). In my case the problem was that I had a Web Project selected as a startup project. Changing it to an class library solved the problem. Once again there is no such problem with Immediate Window.

So basically you can use both tools: the Immediate Window and the Object Test Bench. Both have their advantages and disadvantages, but I have found the Immediate Window to be just better, faster and always there and that is why I'm not using the bench any more.

kick it on DotNetKicks.com

Thursday, December 07, 2006 7:51:19 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, December 05, 2006

In one of my articles I have written about using Immediate Window for debugging purposes - how we can use this Window to debug an application without starting it. Basically you can use the Window, to start a debugging process on any of your methods just by invoking it in Immediate Window:

new MyNamespace.MyType().MyMethod()

or for static methods just

MyNamespace.MyType.MyMethod()

There are however other useful features that make this window even more powerful.

One of them is evaluation of commands. Take for example:

System.Guid.NewGuid()
{04653f8d-58d3-4254-adc8-fb6d95457b49}

Which presents you with a new Guid instance as a string. Nice feature to have since I'm no longer able to find the Generate Guid window in my Visual Studio 2005. This window was very useful when I was working with Visual Studio 2003.

The above is simply a static method call. Lets see what else can we do. The immediate window can be used as a simple (or very advanced when you think about it) calculator. Take for example:

5*5
25

What we get in return is... of course the result of this operation. Still this is also a method call underneath. We can go very far with this, as far as the .NET classes allows us to. If we need an advanced calculator we can use some of the Math's methods:

System.Math.Sqrt(4) + 3.2
5.2

Those are still only simple method calls. The interesting part begins with multi-line statements!

The immediate window allows commands to span multiple lines and include variables. With those you can do almost anything you could do in the normal code:

int x = 2;
2
int y = 3;
3
x + y
5

If you wonder how far you can go with Immediate Window, just consider this example:

System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection("someconnectionstring");
System.Data.SqlClient.SqlCommand cmd = connection.CreateCommand();
cmd.CommandText = "SELECT * FROM SomeTable";
connection.Open();
System.Data.SqlClient.SqlDataReader reader = cmd.ExecuteReader();
reader.Read();
reader[0];

Not that you will use the window for such commands, but it is nice to know what it can really do :-)

BTW: I have noticed that sometimes Visual Studio hides the Immediate Window from me. While doing so it also removes the one place in the menu that I know of that can be used to show the window: Debug->Windows->Immediate. If your Visual Studio also knows better, the shortcut Ctrl+Alt+I will help you.

kick it on DotNetKicks.com

Tuesday, December 05, 2006 9:29:12 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  |