David Foderick's Blog - OnMaterialize()

February 2005 - Posts

I wish I could read German

Ralf Westphal has a download covering an Introduction to Object Relational Mapping using Versant Open Access along with sample code. The code is easy enough to read because its in a language I understand: C# and VB. But the slides are in German. The cool thing is if I stare at the words long enough they sometimes actually seem to make sense. I guess that's because English is really a Germanic language, at least before the Normands invaded England.

On a related note, why does it seem that Europeans are leading the U.S. developers in the area of Object Relational Mapping? Is is a historical thing or a cultural thing? Are all U.S developers under the spell of Microsoft?

Anyway, the code samples show how to use a Winform client calling a Web Service using an ObjectContainer. Great stuff.

 

Restoring users's last window size and location

I have a feature in my Windows form appliation that remembers the application's main window size and location. When the user logs in, I restore the window's size and location to the last known setting. I also use dual monitors at work. What if the user doesn't dock the taskbar to the bottom but instead docks it on the top or right (Longhorn style)? What if the user has multiple monitors? When taking these contingencies into account, the .NET base class libraries help you out. Essentially, you have to take in to account that the working area of the screen can be, and probably will be, different than the total size of the screen. Using a couple of little-known methods in .NET that recognize the Working Area of the screen makes for an improved user experience.

Form.SetDesktopLocation
MSDN says: You can use this method to position your form on the desktop. Since desktop coordinates are based on the working area of the form, you can use this method to ensure that your form is completely visible on the desktop.


So, instead of just setting the Location property of the form, you can do something like this to make sure it is positioned correctly relative the position of the taskbar.

   //Restore the user's last windows location
   this.SetDesktopLocation (
    User.LastWindowLocation.X,
    User.LastWindowLocation.Y
    );

Screen.GetWorkingArea()
MSDN says: Retrieves the working area for the display that contains the largest region of the specified control. The working area is the desktop area of the display, excluding taskbars, docked windows, and docked tool bars.

Instead of setting the Size property of your main form, you can use a calculation like this to make sure the form does not exceed the limits of the screen's working area.

   if (!User.LastWindowSize.IsEmpty)
   {
    Size newSize = new Size (
     Math.Min(User.LastWindowSize.Width,Screen.GetWorkingArea(this).Width),
     Math.Min(User.LastWindowSize.Height,Screen.GetWorkingArea(this).Height)
     );
    this.Size = newSize;
   }

Screen.PrimaryScreen
Screen.AllScreens
These properties of the Screen object reference the user's primary screen and a collection of all the user's screens in the case that they have multiple monitors.

Using these methods and properties can make for a better user experience. Your users won't complain - and they might even thank you!

Modifying a collection through an iterator

As most .NET developers know, the foreach statement will iterate through any collection that implements the IEnumerable interface. The iterator is intended to be readonly, meaning that you cannot modify the underlying collection without severe consequences, namely an InvalidOperationException the next time you attempt to read an element from the collection (via the MoveNext method) after the modification. Therefore, the following code is invalid since it attempts to remove an element from the collection while iterating through it at the same time.

   foreach (DictionaryEntry de in myHybridDictionary)
   {
    if (de.Value != null)
    {
     key = de.Key.ToString();
     myHybridDictionary.Remove(key); //CANNOT DO THIS!
    }
   }

There are several possible resolutions to the problem, such as using for instead of foreach, but the most straightforward is to simply build up a list of elements you want to remove in a separate list and then delete them in a loop at the end. (Using for over a HybridDictionary seems rather clumsy.)

   ArrayList deleteThese = new ArrayList();
   foreach (DictionaryEntry de in myHybridDictionary)
   {
    View view = de.Value as View;
    if (view != null)
    {
     deleteThese.Add(de.Key);
    }
   }
   foreach (String key in deleteThese)




     myHybridDictionary.Remove(key);
Boost your wireless router's power

Do you own a Linksys WRT54G wireless router? Tired of the limited coverage area? I was. When I first set it up I could barely connect from the next room and there is no way to boost the default power level of the antenna with the built-in firmware. Luckily, I happened to purchase one of the coolest router's available for the consumer market. This thing actually runs a version of the Linux operating system and there is a healthy community of activists who are improving the firmware.

So, to get improved reception over a much larger area all I had to do is download a new firware. The free version is code named Satori. You can also pay $20 for better technical support. The interface looks pretty much the same as the one from Linksys except you get more options. One of the new options is to set the antenna power level. I increased it and I now get excellent wireless reception throughout my house. In the summer I can now program from my hammock in the yard. Cool!

Warning! Explicit material!

Often, we create domain model classes that wrap dumb CLR primitives which we then imbue with smart behavior. Wouldn't it be convenient to be able to cast these wrapper objects back to the native value type? You can with something called an explicit operator.

Here you have two classes, one called Money and a support class called Currency. Money is a wrapper for a CLR decimal and a Currency instance.


 public class Money
 {
  private decimal amount;
  private Currency currency;

  public Money(decimal amount, Currency currency)
  {
   this.amount = amount;
   this.currency = currency;
  }

  public static Money Dollars(decimal amount)
  {
   return new Money(amount, new Currency("USD"));
  }

  public static explicit operator decimal ( Money value )
  {
   return value.amount;
  }
 }

 public class Currency
 {
  private string locale;
  public Currency(string locale)
  {
   this.locale = locale;
  }
 }

Notice the explicit operator for decimal. With it, we can write code like this.


   Money money = new Money(1.34M, new Currency("CAN"));
   decimal amt = (decimal)money;

Without it, we would get a compiler error on the casting. There is also support for converting types in the TypeConverter class.
What does O.R.M have to do with R.E.M?

Let's put our heads together and start a new country up
Our father's father's father tried, erased the parts he didn't like

From the song Cuyahoga by Michael Stipe, R.E.M.

Stipe was singing about the polluted Cuyahoga river, but may as well have been talking about the festering cesspool that is the .NET DataSet. The DataSet is a relational thing that exposes rows and columns to your application. It's brain dead when it comes to business objects. You have to do a significant amount of work to use it in a domain model. Is there a better way? Yep - object-relational mapping.

The Cuyahoga project is a sample ASP.NET application in the spirit of IBuySpy with free source code except that it uses object-relational mapping to perform its data access instead of ADO.NET. We need more efforts like this in the .NET community if we ever want to move beyond the DataSet to build agile applications. So let's put our heads together and start up a new way of organizing business logic around custom classes instead of the DataSet.

If you want to use a different color scheme for Cuyahoga than the default red one, download the blue color scheme.

Whitepaper: Introduction to Versant Open Access .NET

I finally finished a paper that I've been working on for several weeks. It's an introduction to object - relational mapping using Versant Open Access .NET. Significantly, it doesn't even mention the ORM word. In a few pages it goes over the deficiencies of the DataSet and why you need a smart data access layer that knows about your business objects when you are working with a Domain Model. It then goes over the mechanics of downloading and installing the product. Finally, it walks through how to build a simple Windows Forms app using the cool wizards and IDE features. I really like the fact that I could create a simple demo that retrieved, edited and persisted domain objects with just one line of code!

I don't know what Versant will do with the article. I think they are planning on distributing it at their booth at VSLive. If you are not going to the show or can't find it on the Versant site, then you can always download it here.