Mapping Enums to custom strings in NHibernate

by Warlock on Jul.02, 2009, under .NET, Database

Many times when working with a legacy relation model and a newly developed C# object model that sits on top of the relational model, you may need to map enum values to/from arbitrary strings in the database using NHibernate.

For example, suppose you have a a work order object that three possible states: request, approved, denied. To represent this, you might use the following enum:

enum WorkRequestState
{
    Request,
    Approved,
    Denied
};

But let’s assume that the legacy relational model has represented these values as strings: REQ, APR, DEN. You can’t change the values for the relational model, and you certainly don’t want to use these values in your enum because they are not as readable as the values shown above.

By default, NHibernate will automatically convert you enum to a string value that matches the name of the enum values if the table field a string, or it will convert to the integer value for the enum options if the table field is an integer.

To do the above custom mapping we must implement a custom NHibernate type.

First, create a new class that inherits NHibernate.Type.EnumStringType. In your constructor, pass the type of the enum you are handling, and the maximum number of characters that the enum values will be to the base class constructor:

class WorkRequestStateEnumStringType : NHibernate.Type.EnumStringType
{
    public WorkRequestStateEnumStringType()
        : base( typeof(WorkRequestState), 3)
    {
    }
    ...
}

Next, override the GetValue(…) method to map the enum value to the equivalent string.

public override object GetValue(object enm)
{
	if( null == enm )
		return String.Empty;

	switch( (WorkRequestState)enm )
	{
		case WorkRequestState.Request	: return "REQ";
		case WorkRequestState.Approved	: return "APR";
		case WorkRequestState.Denied	: return "DEN";
		default : throw new ArgumentException("Invalid WorkRequestState.");
	}
}

Override the GetInstance(…) method to map a string value to the equivalent enum value:

public override object GetInstance(object code)
{
	code = code.ToUpper();

	if( "REQ".Equals(code) )
		return WorkRequestState.Request;
	else if( "APR".Equals(code) )
		return WorkRequestState.Approved;
	else if( "DEN".Equals(code) )
		return WorkRequestState.Denied;

	throw new ArgumentException(
		"Cannot convert code '" + code + "' to WorkRequestState.");
}

Finally, in the NHibernate mapping file, specify the property’s type as the derived EnumStringType class.

<class name="WorkRequest" table="work_request_table">
  <property
    name="Status"
    column="status_field"
    type="my.namespace. WorkRequestStateEnumStringType, MyAssembly" />
  ...
<class>

Note that when specifying this type, you must use the assembly-qualified name because the NHibernate code doing the mapping is in a separate assembly from the type you created.

This information has been derived from Jeremy Miller’s original post here.

Leave a Comment :, , , more...

Cocoa/UIKit BulbView

by Warlock on Jun.18, 2009, under Cocoa, iPhone

In my continuing saga to bring old-school displays to new-school (word?) devices, I’ve created a “bulb view” that displays characters in a grid of “lights”. The best way to describe it is probably just to see it:

BulbView from Mac

BulbView from Mac

BulbView on iPhone

BulbView on iPhone

Like previous LCD view you can set the colors for the lit & dim bulbs, but improved from the LCD view, you can use letters, numbers, and most punctuation/special characters. Again the rendering is done in pure Quartz2D.

The source, including demo apps for both the Mac and iPhone, can be found here. With this view I was smart and made it conditionally compile various parts so that it can be used on either the iPhone or the Mac, without needing separate files.

Leave a Comment :, , more...

Conditional Compilation for iPhone

by Warlock on Jun.17, 2009, under Cocoa, iPhone

I’m working on a view right now that I want to be able to cross compile as either an NSView for the Mac, or a UIVIew for the iPhone. I originally wrote it for Leopard, but now I’m trying to add the precompiler directives to let it cross compile between the two platforms. A quick Google search didn’t reveal anything, here are the possible definitions you can use:

#define __MAC_10_0      1000
#define __MAC_10_1      1010
#define __MAC_10_2      1020
#define __MAC_10_3      1030
#define __MAC_10_4      1040
#define __MAC_10_5      1050
#define __MAC_10_6      1060
#define __MAC_NA        9999   /* not available */

#define __IPHONE_2_0     20000
#define __IPHONE_2_1     20100
#define __IPHONE_2_2     20200
#define __IPHONE_3_0     30000
#define __IPHONE_NA      99999  /* not available */

This definition comes from Availability.h located at /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/usr/include/Availability.h (for the iPhone 3.0 SDK).

Obviously, the __MAC_10_x is actually for the version of OSX, and the __IPHONE_x_x is for iPhone.

So, if you wanted to have code conditionally compile for the iPhone (assuming 3.0 SDK) you would do something like the following:

#ifdef __IPHONE_3_0
    // iPhone
    #import <UIKit/UIKit.h>
#else
    // Mac
    #import <Cocoa/Cocoa.h>
#endif
Leave a Comment : more...

WPF Regular Expression Test Utility

by Warlock on Jun.16, 2009, under .NET, Software Development Tools, WPF

When working on .NET applications, I frequently need to test regular expressions I’m using in my code. There are many good utilities out there to test regular expressions, but most are web-based and rely on Javascript for regular expression processing, which lacks support for .NET’s named captures.

In response, I built the a regex test utility in WPF that has the following features:

  • .NET syntax for regular expressions
  • Supports named capture groups
  • Gives real-time feedback (as you type) for the regular expression and the test input
Screenshot of regex tester.

Screenshot of regex tester.

The binary requires .NET 3.5 and is available here. The source can be found on GitHub here.

Also, for those of you working with .NET regular expressions, I’ve always found this site a great resource.

2 Comments :, more...

Vista-style Checkbox Images

by Warlock on May.27, 2009, under User Interfaces

The following picture contains all the images needed to make a tri-state checkbox on the web. It contains both hover and regular state for all checked modes except disabled. These come from screenshots from Windows Vista, so use at your own risk.

Checkboxes

checkboxes_small

Leave a Comment :, more...

CGColorCreateGenericRGB Error on iPhone SDK 3.0

by Warlock on May.26, 2009, under Cocoa

While porting some Core Graphics/Quartz 2D code from the Mac to the iPhone, I ran across the following error:

error: ‘CGColorCreateGenericRGB’ is unavailable (declared at

/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.0.sdk/System/Library/Frameworks/CoreGraphics.framework/Headers/CGColor.h:31)

Looking in the header file in question (CGColor.h), I found the following:

/* Create a color in the “Generic” RGB color space. */

CG_EXTERN CGColorRef CGColorCreateGenericRGB(CGFloat red, CGFloat green,
    CGFloat blue, CGFloat alpha)
    CG_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA);

So the header file pretty much confirms what the error says; the function is not available on the iPhone.

After a little bit of looking through documentation, you just have to specify the color space manually and then give the components to the color. So the this:

CGColorCreateGenericRGB(0.90625, 0.80, 0.80, 1.0)

would become


CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
const CGFloat myColor[] = {0.90625, 0.80, 0.80, 1.0};
CGColorCreate(rgb, myColor);
CGColorSpaceRelease(rgb);

Leave a Comment :, , more...

Cocoa LCD Screen View

by Warlock on May.25, 2009, under Cocoa

As part of an iPhone application I’m developing, I need a view that will display numbers/times in a way that will look like an old liquid crystal display calculator. I looked around at using various fonts to cover the same effect, but I wanted the look where you could slightly see the non-lit components of the display. As such, I delved into the mystical world of Quartz 2D.

Example of the LCD view showing the current time.

Example of the LCD view showing the current time.

MTILcdView allows you to set three parameters: the color for the “lit” crystals, the color for the “dim” crystals, and the text to be displayed. The view currently only supports displaying numbers plus the colon (”:”) per my needs, but it could easily be extended to display letters as well. The view decides the size of the digits to be displayed based on the height of the view, so for a given height you must adjust the width of the view to allow the needed number of characters to be displayed.

The source code for the Mac is available here: MTILcdView.h, MTILcdView.m. A complete demo application using the view can be retrieved from GitHub here.

MTILcdView running on iPhone

MTILcdView running on iPhone

The source code for the iPhone 3.0 SDK is available here: MTILcdView.h, MTILcdView.m (note that you must manually rename the files from MTILcdView1.{h|m} to MTILcdView.{h|m}). A complete demo application using the view can be retrieved from GitHub here.

1 Comment :, , , more...

ASP.NET 1.1 pages/assemblies take a long time on first load

by Warlock on May.18, 2009, under .NET

The first time you load a page on an ASP.NET web site, or the first time you access a .NET web service, it may take significantly longer to load than subsequent accesses. There are several things that can cause this, including the framework compiling the aspx source pages, but there can be an even more significant delay if you are using Authenticode-signed assemblies and your server does not have access to the internet. In the case of web services, this delay may even be long enough to cause timeouts depending on the configuration of your client programs.

The problem is that as .NET loads Authenticode signed assemblies, it must check for updates on the certificate revocation list (CRL) to verify the signature on the assembly is valid. If Active Directory is not configured to have the authority for CRLs on the local network and the server in question does not have a connection to the internet, the request for the CRL will time out after approximately 15 seconds, and .NET will continue loading the assembly and consider it to be unsigned. This problem is discussed in several articles.

To verify this is what’s happening, you can use a packet sniffer on the server in question and look for the request for the CRL. Using Wireshark, I was able to observe the following behavior after I had stopped the World Wide Publishing service, started the trace, relaunched the World Wide Publishing service, and made a request:

Request for CRL

Request for CRL

The above screenshot shows that a request was made for http://crl.microsoft.com/pki/crl/products/CodeSignPCA2.crl (IP address 96.17.76.91).

Note that the request will not always be made. The CRL is always cached for the lifetime of a process, so if the IIS worker processes continue to run you will not get a request for the CRL. It’s possible that the CRL is cached for longer, though I haven’t been able to verify that this Microsoft Technet article describes many things about the Windows PKI, including CRL caching. I can replicate the above results when I first stop the World Wide Publishing service, clear the cached data from Internet Explorer, start the trace, start the World Wide Publishing, then make a request to the ASP.NET page/web service. For computers that are not connected to the internet and have not been for a long time, I would guess any caching for the CRL would expire, and every time an Authenticode signed assembly is loaded Windows would try to refresh the CRL. On Vista, you can explicitly refresh the CRL cache per this article.

Resolving this issue on .NET 2.0 post SP1 is straightforward. Setting the generatePublisherEvidence configuration option to false will skip the CRL check. This issue is discussed in Microsoft KB936707.

On .NET 1.1, things are not as straightforward. There isn’t a configuration setting to disable the authentication behavior. The only solution is to disable CRL checking for the entire machine. This can be accomplished through the following steps, originally described on this website.

  1. Open Internet Explorer
  2. Go to Tools —> Internet Options…
  3. Go to the Advanced tab
  4. Locate the Security section and uncheck the Check for publisher’s certificate revocation option.
    Disable Check for publisher's certificate revocation option.

    Disable Check for publisher's certificate revocation option.

CRL checking can also be disabled throughout the entire organization per this Microsoft Technet article.

Another option to address the symptoms as opposed to the underlying issue is to change the behavior of the IIS worker processes. As mentioned previously, the CRL is cached throughout the lifetime of a process, so by managing the lifecyle of the worker process, you can force this timeout to come during non-work hours.

In IIS manager, view properties for the app pool under which your ASP.NET application is running. Go to the Performance tab and disable the idle timeout of the worker processes.

Disable worker process idle timeout

Disable worker process idle timeout

Next, go back to the Recycling tab and set the processes to only recycle at a certain time of day (e.g. 2:00 a.m.).

Change app pool recycling to non-business hours

Change app pool recycling to non-business hours

The last step is to create a custom script that will make a request to your application shortly after the worker processes have been recycled. This will force the CRL check at a time when it doesn’t matter how long the first request takes as normal user activity won’t be interrupted.

Leave a Comment :, , , more...

jQuery Plugins

by Warlock on May.16, 2009, under Javascript

Yesterday I spent several hours going through the UI jQuery plugins and compiled a list of the most interesting to me. Bear in mind that in many cases interesting to me is driven by the fact that I work with scheduling software.

  • FullCalendar month-view calendar that supports drag and drop of events (demo)
  • AutoScroll script to automatically scroll an element as you near an edge
  • jCal large, multi-day day picker control
  • jEditable control that allows arbitrary text to edited inline when clicked
  • jGrowl plugin to create a Growl-like effect on a web page
  • Growl another plugin to create a Growl-like effect on a web page
  • DynaTree dynamic tree view (demo)
  • jScrollPane javascript scroll bars (demo)
  • Purr yet another Grow-like effect on a web page. This one has the nicest visual presentation of those listed.(demo)
  • QuickSearch javascript search field that eliminates non-matching elements from a table
  • SemanticTabs jQuery tabs
  • uiTableFilter filters elements of a table based on a search field
  • Throbber jQuery loading circle (demo)
  • TimePicker jQuery timepicker
Leave a Comment :, more...

UIButton Title Text Does Not Display

by Warlock on May.14, 2009, under Cocoa

Ran into a minor problem today when I was attempting to manually create a UIButton in my iPhone app. I attempted to create/configure the button through code similar to the following:


CGRect frame = CGRectMake(0, 0, 200, 52);
UIButton b = [[UIButton alloc] initWithFrame:frame];
b.titleLabel.text = @”My Button”;
b.titleLabel.textColor = [UIColor whiteColor];

b.backgroundColor = [UIColor clearColor];

The key mistake is highlighted in red. I attempted to manually set the text an color of the UIButton’s label, when in fact the UIButton would automatically reconfigure the label (including it’s text) in response to state changes.

The correct approach is to use send the setXXX:forState: messages to the UIButton object itself. For example, the following code sets the text/color for the UIControlStateNormal state.


[b setTitle:@"Test" forState:UIControlStateNormal];
[b setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];

1 Comment : more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Visit our friends!

A few highly recommended friends...