Friday, June 29, 2007

ADO.NET 101

I'll file this under the "stupid mistakes" category, but I'll admit to it here just in case someone else didn't realize this until it was too late like I did.

When you have a SqlDataReader open, you can't reuse the underlying SqlConnection. In my case, I just changed to using a DataSet instead of a reader (I don't remember why I used a reader in the first place... the query always returned 1 row). Another solution would be to open a second connection.

This support document puts it quite succinctly:

While the SqlDataReader object is in use, the associated SqlConnection object serves the SqlDataReader, and you cannot perform any other operations on the SqlConnection object other than to close it. This is true until you call the Close method of the SqlDataReader object.

Friday, June 22, 2007

Annoying Xcode problem

Taking a bit of a jaunt off into left field from my usual .NET posts...

I was trying to create a Java project under Xcode in Mac OS X 10.4. Strangely, right out of the box the template application project compiled but didn't run. I kept getting a java.lang.UnsupportedClassVersionError.

Seems that after Java 1.5 came to the OS X platform, it gets selected as the default JDK for compilation, but Xcode thinks it's still working with a 1.4 target so it creates a script that starts the app using 1.4.

Once you realize that, it's easy enough to change the settings in the project to fix it. This Apple Q&A explains it in detail.

Thursday, June 21, 2007

References and classes... make sure you mean it

All too often, I see things like this:

C#:
public void DoSomethingToAClass(ref AClass objectToChange)
{
// ... change some member variables of objectToChange or whatever
}


VB.NET:
Public Sub DoSomethingToAClass(ByRef objectToChange As AClass)
' ... change some member variables of objectToChange or whatever
End Sub


This is totally redundant. Classes are reference types. Therefore, by default they are passed by reference. This means that you can drop the ref or ByRef and achieve the same results. What's worse is that in the examples above, you're creating a reference to a reference, which just creates extra work for the application dereferencing them twice to find the actual object.

On the other hand, if what you're passing in to the method is a value type, then this is what you want. Your intrinsic types (such as Int32) and struct (C#) or Structure (VB.NET) are all value types. These need the ref or ByRef tag, otherwise your changes will be lost when the method exits. Note that while Arrays and Strings are also technically reference types, the framework handles them somewhat differently, and you must use ref or ByRef with them to get the desired result.

There are times when a reference to a reference is what you want, especially with certain P/Invoke methods that ask for a "pointer to a pointer" as one of the parameters. In this case, using ref or ByRef with a reference type makes sense and is what you want.