Wednesday, December 21, 2005

VS2005 Design-time set DataSource error III

Design-time data-binding in .NET 2.0 WinForms is a real productivity booster that I use extensively. I have, however, had some problems with using the new object binding source mechanism (error I, error II) and today yet another problem. I began designing a new user-control a few days ago, and being a lazy developer, I copied some data bound comboboxes that I needed from another user-control.

I should have know better, copying controls was a recipy for immediate disaster in the VS2005 betas; you could be sure that the Visual Studio designer would fail when you later on re-opened the user-control. The same applied to renaming a control after modifying some of its properties. These problems have been fixed in the release version of VS, although opening a form still randomly causes the cursor to go into a blink frenzy for quite some time while re-syncing with the .Designer file.

Copying those combos kept some of the data binding properties (ValueMember, DisplayMember), but did not copy the binding sources (more on this below). I added the object binding sources in the 'Data Sources' explorer, and after some refreshing of the project data sources (error II), object binding seemed to work properly.

Today, I added another object binding source to the 'Data Sources' explorer of the user-control. If I then tried to use the DataSource property at design-time, I got this error:

Object reference not set to an instance of an object

Setting the data binding at run-time work fine. So does copying the original data source binding code from the hidden .Designer file, it even shows correctly in the control properties explorer, but cannot be changed due to the above error. But this is not how I want to do it, I wanted design-time binding to work. Any attempt to modify data binding on any controls in the form would cause the design-time error.

In an attempt to fix the binding problems, I used an old trick when working with software and computers; I restarted Visual Studio, opened the solution and cleaned it. Then I clicked the DataSource property of my failing combo. Now I got this error, which anyone who have parsed XML will recognize:

Root element is missing

After Visual Studio had shown this puzzling error (as usual no intelligble info provided in the message), all design-time data binding worked properly again and the combos were filled at run-time. Oh joy! . . . But the object binding source that I had added lastly, was gone from the 'Data Sources' explorer. As long as the design-time binding kind of worked again, I could live with that.

I suspected that there was a problem with one XML files in the solution and checked the various .RESX files and some other files with XML content, but I was not been able to find any error. When I had just about given up, I noticed that the three listed data sources in the 'Data Sources' explorer also happened to be the three first .datasource files in the \My Project\DataSources\ folder (use 'Show all files' in the 'Solution Explorer'). Thus, I opened the fourth .datasource file, and voila, it was empty! Visual Studio clearly just stops looping through the data sources when it encounters an error.

I excluded the empty file from the project, reloaded the solution, and then all the project data sources were listed in the 'Data Sources' explorer. Design-time binding now works as expected again. Oh, even more joy!

I am still sceptical to copying object bound controls from one WinForms user-control to another. The VS designer might punish you. Maybe I am just being paraniod.

Monday, December 19, 2005

VS2005 Crash on binding to data source II

Today I got a problem with VSTS 8.0.50727.42 that caused Visual Studio to just die, sometimes even without opening the error reporting dialog. This happened when trying to bind a DataGridView to a newly added object data source by using the popup toolbox of the grid. VS would vanish when I clicked the 'Choose data source' combo. No error message.

As I have had problems with the VS2005 data source mechanism before (data source crash I), I have some experience in troubleshooting data sources. I stared out checking for invalid, zombie data sources in the \My Project\DataSources\ folder (VB.NET), and removed an old, unused data source. This did not solve the problem, but I prefer to diagnose a clean solution.

When I made the new business entity object that I was adding as the new binding source, I also refactored some of the other entity objects to remove some obsolete properties and changed some property names to reflect gained knowledge about the domain.

I found out that VS2005 is not fond of such changes in the assemblies used as object binding sources. It is however, quite easy to make the data sources reflect the changes:
  • Select the project in the solution explorer
  • Click the 'Show all files' button
  • Navigate to 'My Project' and expand it
  • Navigate to the 'DataSource' child node and expand it
  • Select each of the data sources in turn
  • Right-click the data source and select 'Refresh'
Note that there is no refresh option on the 'DataSources' node in solution explorer, you have to manually refresh every single data source in your solution.

After refreshing the data source definition cache as described, VS2005 no longer performs harakiri in response to refactoring objects used as data sources.

Friday, December 09, 2005

.NET deep clone - IsDirty check using IsClone<T>

Those of you that read my colleague Anders Norås' blog may have tried the deep clone using serialization method (see also article at MSDN Mag). This is really useful e.g. when implementing undo, transactions, and other mechanisms that need to make copies of objects.

[UPDATE] Refer to this post for a faster IsDirty check and more reliable IsClone method: IsClone using custom formatter.

Another useful appliance of the clone method is for implementing an IsDirty property in your business entity objects or in other areas of your application. I have implemented an IsClone method that checks whether two objects are identical or not:

public static bool IsClone<T>(T sourceA, T sourceB)
{
IFormatter formatter = new BinaryFormatter();
Stream streamA = new MemoryStream();
Stream streamB = new MemoryStream();

formatter.Serialize(streamA, sourceA);
formatter.Serialize(streamB, sourceB);

if(streamA.Length != streamB.Length) return false;

streamA.Seek(0, SeekOrigin.Begin);
streamB.Seek(0, SeekOrigin.Begin);

byte[] hashA = new System.Security.Cryptography.MD5CryptoServiceProvider().ComputeHash(streamA);
byte[] hashB = new System.Security.Cryptography.MD5CryptoServiceProvider().ComputeHash(streamB);

for (int i = 0; i < 16; i++)
{
if (hashA[i] != hashB[i]) return false;
}

//if here, objects have same hash = are equal
return true;
}


The "source" objects must of course be deep serializable. The method uses hashing to achieve good performance. The compare using MD5 is based on code by Corrado Cavalli for fast comparison of byte arrays.

Wednesday, December 07, 2005

TFS server restored - I miss SourceSafe's checkout options

The TFS server (beta 3 refresh) of our project had to be re-installed due to database problems, but I continued working offline (without TFVC) on the components that I am solely responsible for. I have done this many times before when SourceSafe has been unavailable due to no access to the "database" file share. Afterall, as a consultant I am often required to make changes to a previous project deliverable after moving on to the next customer. Sometimes I even have to fix bugs (a rare experience for me).

Today, the TF Version Control system was operational again. The TFVC responsible rebuilt the project from his last good known copy of the source files. Time for me to merge in my "offline" changes. I opened the 'Source Control Explorer', browsed to the project and selected 'Get latest version (recursive)'. TFS dutifully discovers and lists the source files that I have made changes to, and prompts me to resolve the conflicts (conflict type is 'Writable file').

TFVC provides you with three options for resolving writeable file conflicts:

  • Check out and auto merge: nice when it works, but it never did for me
  • Overwrite local files/folder: does exactly what it says, just remember to make copies of your "offline" work
  • Ignore conflicts: pointless option as TFVC will fail later on if you try to checkout a writeable file

Note that if you try to check out a writeable file, you will get this error: "Checkout error or user cancellation - File was not checked out".

Where did the useful SourceSafe checkout options for writeable files go ? As I am sure that sometimes in the future I will have to make offline changes to files, I miss these two options in TFVC:

  • Check out and replace: yes, I made some changes, but I want to discard them now, and then continue working on the file to implement the needed changes
  • Check out and leave: yes, let me keep my changes - AND - make it easy for me to add my changes to this file to TFVC

Please, can I at least have the 'check out and leave local file' option back ? Pleeease, TFVC team !

TFVC is really cumbersome when merging "offline" changes back into the version control system:

  1. Make a backup of your offline files using Windows Explorer before even thinking about using TFVC
  2. Perform 'Get latest version' to see which 'Writable files' conflicts there are, and remember the list of files
  3. Resolve all conflicts with 'overwrite local files/folder', unless the 'auto merge' option works for you; the 'ignore' option takes you nowhere
  4. Perform 'Check out for edit' on the files, note that this will only work if you first have "resolved" the conflict by overwriting your offline changes
  5. Replace the old versions of the changed files with the "offline" files using Windows Explorer
  6. Finally check in the 'pending changes' set of source files

You will soon find out that the above should be done with a small set of files at a time, as it is easy to loose track of which source items have been merged or not.

I wonder what kind of usability tests they do at Microsoft to think that TFVC will always be available/online, or to decide that options that were available in SourceSafe for a good reason is no longer needed in the brave new team foundation world. Maybe it is true that the TB manager is so oblivious to the community that he had never heard of CruiseControl.NET.

Tuesday, December 06, 2005

TFS server down - continue working in VSTS

Yesterday our TFS server (beta 3 refresh) started behaving strangely; if I checked in a file and then immediately viewed the file through 'Source Control Explorer' history, it would open the correct file (correct file name in the titlebar), but it contained MSBuild XML content insteadof the original code. This did ofcourse cause all server-side builds to fail. The project's TFS gurus are working on restoring the different TFS databases in the correct order, but this has turned out to be non-trivial. TFS seems to work fine for a while, then the problems are back.

Thus, we are not able to use TFS as of now, but I need to continue working locally on my PC. The default source control settings in VS2005 is not very useful when a connection to TFS cannot be made; it will try to check out files and then just fail, not giving any fallback options. I had to make these changes to 'Checked-in items' in the VS2005 options to be able to 1) edit files and 2) save them locally:


Note that you must clear the 'read only' attribute of a file to be able to save it. Just select the file to overwrite in the 'Save as' dialog, then use 'alt-Enter' to change the properties of the file.

The old SourceSafe 'overwrite' option popup is not available when editing and saving a file that is under source control. You need to change the TFVC options before you can edit and save the file.

The reason for trying to restore the databases is that one of the developers could not delete a test project from TFS using the TFSDeleteProject tool, and then manually deleted some records in the database. The gurus have just given up the restore activities, and are now reinstalling TFS from scratch...

The morale: don't mess with stuff that works.