Archive for August, 2007

Good Quote

Aug 31

My project manager had a qood quote about impossible deadlines I thought I would share.

“you can not make a baby with 9 women in one month”

Very suiting quote for lots of projects I have worked on.

Filed Under: General

Setting A Label From A Different Thread

Aug 29

We have the scenario where multiple labels values are being set from a different thread. When this happens an exception is thrown as labels (and most other controls) are not thread safe. To get around this you can have the hosting form do a BeginInvoke to queue the message to the proper thread (I think that internally it does a SendMessage to the form to do the actual work). 

To do this I create a delegate to a method that sets the labels value:
Private Delegate Sub SetLabelDelegate(ByVal value As String, ByVal label As Label)

Then I create the method:
   Private Sub SetLabel(ByVal value As String, ByVal label As Label)
           label.Text = value
  End Sub

Now just to make things simple I always just call SetLabel() but inside that method I check if we require an invocation (i.e. we are calling the method from a different thread). Final code looks like this:

Private Delegate Sub SetLabelDelegate(ByVal value As String, ByVal label As Label)
   Private Sub SetLabel(ByVal value As String, ByVal label As Label)
       If Me.InvokeRequired() Then
           Me.BeginInvoke(New SetLabelDelegate(AddressOf SetLabel), New Object() {value, label})
       Else
           label.Text = value
       End If
   End Sub

Filed Under: General

Things I Learned About FoxPro

Aug 28

On my current project I have to connect to a legacy FoxPro2 database. I know nothing about FoxPro but it was fairly easy to connect to and use in ADO.NET. I had a few stumbling points that I thought I would share in case you have to connect to one.

1. Named parameters are not used by oledb/odbc commands. They are ordinal and represented by question marks:
command.commandText = “insert into users (firstName, lastName) values (?, ?)”

The commands then need to be added in the correct order:
command.parameters.add(“@firstName”, customer.firstName) command.parameters.add(“@lastName”, customer.lastName)

I know I show the parameters as named in the add() method but I could call them whatever I wanted. It is imperative that they are in the right order otherwise it will not work properly. I am under the impression that only SqlCommands take named parameters but I could be wrong on that.

2. When you get “OleDbException: Variable is not found”. It means that the column you are querying does not exist (I had a small typo in my query and it took me a long time to figure this out).

3. When doing a query like this:
insert into users (firstName, lastName) values (?, ?)
yet there is a column called PhoneNumber in the table you will get the error:
“Field PHONENUMBER does not accept null values”
From my reading FoxPro does not have a null type so it fails on this query. The only way I got this to work was to switch from an oledb provider to an ODBC provider and uncheck the “Null” checkbox in the ODBC options for my foxpro DSN.

4. The error message: “Driver Not Capable” occurs when you try to insert a complex type (i.e. an object) instead of a primitive. Not the most descriptive error but easy enough to fix.

5. When setting up a foxpro ODBC connection you will get an error saying you need to download the latest driver. You should download the latest Visual Foxpro Driver (yes even if you using FoxPro not Visual FoxPro). Then configure your connection using the FoxPro VPF Connection. Under database type there will be two options to use a DBC database (visual FoxPro) or to use a Free Table Directory. Use the Free Table Directory option as legacy FoxPro creates a file per table in a set directory and that is your “database”.

6. This applies to everyone. CODE TO INTERFACES. By coding to the IConnection, ICommand, etc. interfaces my switched back and forth between odbc and oledb took seconds not days.

Filed Under: General

Extension Methods For Casting

Aug 27

I have not played much with orcas or .NET 3.5 but had an interesting idea so had to crack and get it up and running.

One thing I have not liked is having to cast/parse types as it leads to harder to read code in some situations . i.e.:
int myInt = int.Parse(((customer)value).SocialInsuranceNumber)
or
dim myInt as integer = integer.Parse(ctype(value, customer).SocialInsuranceNumber)

So playing around with extension methods I got code like this that is a bit more fluent:
int myInt = value.CastTo<customer>().SocialInsuranceNumber.Parse<int>();

I find this a lot more readable. Here is the code:

public static class CastExtension
    {
        public static T CastTo<T>(this object value)
        {
            if (value == null) throw new ArgumentNullException(“can not cast a null value”);
            return (T)value;
        }

        public static int ToInt(this object value)
        {
            if (value == null) throw new ArgumentNullException(“can not cast a null value”);
            return int.Parse(value.ToString());
        }

        public static T Parse<T>(this object value)
        {
            T parser = (T)Activator.CreateInstance(typeof(T));

            System.Reflection.MethodInfo mi = parser.GetType().GetMethod(“Parse”, new Type[] { typeof(String) });
            if (mi == nothing) throw new ApplicationException(“can not parse on a type that does not implement Parse(string)”);
            return (T)mi.Invoke(parser, new Object[] { value });
        }
    }

I hate the implementation of the parse method but until I find a better way… it works. I wish that the type.Parse() methods implemented a generic interface or something along those lines as I had to use reflection to execute the Parse() method on the objects. I also implemented a ToInt() extension for an example as well so that it did not have to use reflection but I figured this would get quite chatty to implement all the different type conversions.

Filed Under: .NET

Datasets Vs. DTOs

Aug 6

On my current contract the powers that be feel that datasets are the way to go for everything and it has become their new standard. While I feel that datasets are powerful and useful in some (rare) situations I feel that this is a bad idea. I did not find much on the comparison between the two techniques so I thought I would write one up. Please don’t take this as an attack on datasets typed or untyped). I am just pointing out why I avoid them for most apps. I appreciate any contributions to this post either for or against datasets.

Terminology
Dataset: (ok everyone reading should know this)
TypedDataset: An object that is generated from an xmlschema that has all the functionality of a dataset plus gives you strong typing and intellisense when using it (always try to use a typed dataset if using dataset at all as it saves time and you do not have the string for column names scattered everywhere)
DTO (Data Transfer Object): A custom object that is used to transfer information i.e.:
public class Person
{
     private string firstName;
     private string lastName;

     public string FirstName
     {
         get{ return firstName; }
         set { firstName = value; }
     }
    
    …property implementation of lastName
}

Re-useability of Parts
If two datasets needed an address table it would have to be re-created in both datasets (i.e. if the person had an address table and company had an address table then you would have to duplicate your effort by creating two identical address tables). By using a DTO you could create one address object and re-use it where needed.

Lack of Control for Messages
By this I mean that you can not control how many records get passed between methods. For instance if I have this method:
public void UpdatePerson(Datasets.Person person)

A developer might get all people, iterate through the dataset to find the right person, change that person, and then send the whole dataset back to update one person. A more experienced developer might do a dataset.getchanges() to only send back the modified records (or call a get method that only retrieves the person they are looking for if it exists). The problem with this is that it is now up to others to make sure that they don’t bombard you with data and in the real world people don’t usually think about the size of messages being sent/received until it becomes a performance issue.

By having a concise method signature using a DTO it makes in impossible for a consumer of the method to send more than one record:
public void UpdatePerson(Entities.Person person)

And if the method was supposed to take multiple records:
public void UpdatePeople(IList<Entities.Person> person)

Mindset
So far I have found that when people use datasets for their transfer objects that the dataset is a mirror of their database and the application turns into one big dataset validator. This is not always the case of course but I find that due to datasets behaving like a database that developers simply copy the database structure. Usually with creating a DTO developers seem to develop more towards the domain objects and map those objects to the database where appropriate. I find that doing DTOs makes me think a bit more about what I am doing and the best way to represent objects in the system instead of representing the data in the system

Extendability
Datasets have a lot of built in functionality already which can be a blessing and a curse. To add functionality to a dataset you can use partial classes in .NET 2.0 and up. While this is a perfectly valid technique it makes me cringe. The reason for that is that to add functionality onto a dataset you are creating new files and then to support that feature you are now hunting around for those partial class files (granted a good file organization structure can help with this but Jr. developers seem to never want to create folders in solutions).

To extend a DTO… simply add the functionality. It’s in the same file, it’s simple, and it is fast.

Clarity
My biggest issue with using a dataset is that it exposes things that users of the object will rarely or never need:

Properties Methods
CaseSensitive
Container
DataSetName
DefaultViewManager
DesignMode
EnforceConstraints
ExtendedProperties
HasErrors
IsInitialized
Locale
Namespace
Prefix
Relations
RemotingFormat
SchemaSerializationMode
Site
Tables
AcceptChanges
BeginInit
Clear
Clone
Copy

CreateDataReader
Dispose
EndInit
Equals
GetChanges
GetDataSetSchema
GetHashCode
GetObjectData
GetService
GetType
GetXml
GetXmlSchema
HasChanges
InferXmlSchema
Load
Merge

ReadXml
ReadXmlSchema
ReferenceEquals
RejectChanges
Reset
ToString
WriteXml
WriteXmlSchema
All the items I have ever used are bolded

And that is just the dataset object! The same concept applies to datasets. As you can see this exposes way more than is required to consumers of the object. With a DTO we can add only the methods that are required and keep the object much easier to use.

On the topic of easy to use which is easier:
Datasets.PersonDataset ds = new Datasets.PersonDatasset
Datasets.PErsonDataset.PersonRow row
row = ds.People.NewPeople()
row.FirstName = “Alex”
row.LastName = “Kieth”
ds.People.AddPeople(row)

Or:
Entities.Person person = new Entities.Person()
person.FirstName = “Alex”
person.LastName = “Alex Kieth”

Required Values
It is a pain to force the creation of a datarow with certain values. A factory method is probably the way to go for this but a consumer has the ability to just use the raw datarow still. With a DTO we can easily force required values via the constructor:
Entities.Person person = new Entities.Person(“FirstName”, “LastName”)

For a datarow we would have to write code to validate that the proper information was present and if not return an error back to the consumer (or throw an exception). This validation needs to now be in place where ever the datarow can be used.

Creation Time
This is where I feel that typed datasets win. They are fast and easy to create. A DTO takes time to create the fields and properties…. unless you are using a refactoring tool like Resharper and then I would say that the times are comparable for creation of the object.

Testing
A DTO is easy to drive out when using TDD and Resharper whereas with using a dataset there is a real time hit switching back and forth from your dataset designer. Datasets are not easy to mock out for those that use mocks.

Abstraction
I have never tried to create an interface for a typed dataset but I am sure I would not want to. If I wanted to create a proxy to a DTO is would be as simple as implementing the same interface on both the real and proxy classes. To do this for a datarow….. I would not want to think of what is required to do this.

Debugging
Datasets lead to data adapters and data adapters lead to drinking. There I said it. While the dataadapter and dataset work really well together it is impossible to debug (I usually end up profiling SQL to see what is actually happening to debug any issues at this point). While using a DTO is usually more code to map to and from your database (unless you are using an ORM), it is much easier to debug and walk through.

Performance
Apparently in .NET 2.0 the performance of serializing and deserializing a dataset is in binary and much faster and smaller than the old xml way. That being said you are still serializing a lot of extra objects and properties that probably are not required. A DTO only has what is required in it so serialization should always be faster and smaller when using a DTO. It is also easier to customize your serialization for a DTO

Conclusion
As much as I tried to keep this balanced…. its not. DTOs have so many advantages compared to the dataset that I can not fathom using a dataset for a transfer object. The only times would be when I needed an object format that could tell the state of records or when I was building a really simple app that would not change (and we know that there are no apps that don’t change). The DTOs big disadvantage is creation time but most refactoring / codegen tools will easy that pain away. All in all I would probably use a DTO in 95% of cases and in the rare case use a typed dataset or a plain dataset. 

Filed Under: General