Mad Props!

Omniscience is just a Google-search away.

Login

You're reading Mabsterama, the weblog of Matt Hamilton. Enjoy your stay.

LINQ to SQL and NOLOCK Hints

In our SQL queries here at work, we use the NOLOCK hint a lot. Not locking rows during reads is very important to us, and our transactions are seldom rolled back so the queries generally return data that's accurate enough for the tasks at hand.

Now that we're starting to investigate LINQ to SQL, then, we're realising that the queries themselves don't allow any kind of hints. They're generated from your code and passed to the server without any intervention from you.

How, then, can we achieve the equivalent of WITH (NOLOCK) when using LINQ to SQL? The answer lies in transactions.

The NOLOCK hint is essentially the same as wrapping a query in a transaction whose "isolation level" is set to "read uncommitted". It means that the query doesn't care if stuff is in the process of being written to the rows it's reading from - it'll read that "dirty" data and return it as part of the result set.

Turns out that you can do the whole "read uncommitted" transaction thing using the old System.Transactions namespace introduced in .NET 2.0. Here's some sample code:

using (var txn = new TransactionScope(
TransactionScopeOption.Required,
new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted
}
))
{
// Your LINQ to SQL query goes here
}

So I'm creating a new TransactionScope object and telling it to use a read-uncommitted isolation level. The query within the "using" statement now acts as if all its tables were reading with the NOLOCK hint.

That's pretty handy to know! Of course, I'm still on the cusp of moving to a stored-procedure-based system where I can tailor the queries myself. Anyone got any opinions on that front?

AWDNUG February and a Geek Dinner

Last night was our February meeting of the Albury/Wodonga .NET User Group - our first for 2008.

In lieu of any presentations, we spent the night talking about each other's projects and goals for the year. It was a great discussion.

AWDNUG's attendance has been dwindling of late (there were only six of us there last night) so we really need to do something to promote the group. The weird part is that the email that gets sent out every month to let people know what's going on is addressed to around twenty people, so a good 60-70% of members just aren't bothering to show up.

I am keen to return to the "two presentations" format that we started with, and hopefully if we get the right presentations (or the right presenters) we can attract more attendees. If you're ever travelling between Sydney and Melbourne and would like to present for us, please let me know.

We also resolved to have our first "Geek Dinner" which will be a casual affair at the Boomerang Motel on Tuesday that 26th of February. Be there at 7pm if you want to "meet and eat" with a bunch of fellow geeks. We'll also use that night to discuss the prospect of moving our regular meetings to a Tuesday night instead of Wednesdays, to see if the day is the cause of the drop in numbers.

So anyway - hope to see you there on Tuesday the 26th.

Window Reuse in WPF

Really happy with some code I put together for Comicster on the weekend.

For any item in your collection, it's possible to "connect" it to Comicster's online database (hosted here at madprops.org). Once connected, you can quickly upload or download changes to synchronize that item with the online version.

To initially connect an item to the online database, of course, you need to locate the online version. You do so by searching for it using a dialog like this:

image

It's a pretty simple dialog, but of course the logic behind it has to change depending on what you're searching for. A search for creators (like "Stan Lee") should return a completely different set of results than a search for titles (like "Amazing Fantasy"). Not only that, the way results are displayed should change depending on what you're searching for: a search for titles should list the titles' publisher and release year, while a search for creators should list their name and web address.

I didn't want to create a different dialog for every search type, so I decided to approach the problem by passing in logic (both functional and UI logic) to the same dialog depending on what I'm searching for. Witness the dialog's constructor signature:

public OnlineSearchDialog(string searchText, 
Func<string, System.Collections.IList> searchFunction,
DataTemplate resultTemplate)
{

So I'm passing some initial text to search for, and then two interesting arguments:

  1. A function that tells the dialog how to search, and
  2. A DataTemplate that tells the dialog how to display its results

This means that I can construct the dialog like this for title searches:

new OnlineSearchDialog(
title.Name,
t => _service.FindTitles(
new Online.FindTitlesMessage
{
SearchText = t,
DetailRequired = Online.TitleDetailRequired.All
}),
this.Resources["TitleSearchResultTemplate"] as DataTemplate);

and like this for creator searches:

new OnlineSearchDialog(
creator.Name,
t => _service.FindCreators(
new Online.FindCreatorsMessage
{
SearchText = t,
DetailRequired = Online.CreatorDetailRequired.None
}),
this.Resources["CreatorSearchResultTemplate"] as DataTemplate);

See what I mean? I get to pass in all the logic that's specific to the item type I'm searching for.

Passing DataTemplates around like this is not something I've thought of before now, but I feel that it's a great way to make use of the power of WPF. Have you done something like this in your own projects? Leave me a comment!

C# Feature Idea: Static Extension Methods

Extension methods are really useful - no two ways about it. Being able to add my own methods to an existing class makes for some very readable code.

Extension methods, however, are currently only instance methods. There's no syntax for defining a static extension method on a type rather than an instance. For example, suppose I wanted to define a static method called Yesterday() on the DateTime class, so I could do this:

var d = DateTime.Yesterday();

It's a trivial example, I know, but you get the idea. Another example might be to create a static method to create an instance of a type - like the TryParse() method we get on a few inbuilt classes.

I'm thinking that the syntax could use generics and look something like this:

public static DateTime Yesterday<this DateTime>()
{
return DateTime.Today.AddDays(-1);
}

So I've used the "this" keyword (in much the same way that normal extension methods do) except I've used it in the generic type argument. DateTime now has a static method called Yesterday.

Obviously static extension methods would only call static members (unless they take a parameter).

Perhaps C# 4.0 could introduce a feature like this. Would you use it?

Overcoming Sorting Performance Issues in WPF

In my latest WPF version of Comicster, I've been having some performance problems when trying to sort large numbers of issues.

My collection of about 1,100 comics is pretty measly when compared to those of serious collectors', and one file I have from a user has about 10,000 issues in it. When I first open the collection, the root "Owned" folder has focus, so the issue list is populated with every issue in the collection.

Now, populating a ListBox with 10,000 items in WPF is not really a problem, because the ListBox control uses a VirtualizingStackPanel as its default panel. That means that it only needs to worry about the items that are currently displayed, so it should be lightning fast.

The problem is that I'm trying to sort the issues before they're displayed (using CollectionView.SortDescriptions). Sorting 10,000 items by four different properties is slow - there's just no getting around that.

What to do? The issues ListBox is agnostic when it comes to its data source - I couldn't sort it sometimes and not others.

In the end I came up with this idea: An IValueConverter which, given a CollectionView, sorts it if it has fewer than 1000 items. This seems reasonable, because really you only care about sorting if you're viewing a folder, trade or title with a reasonable number of issues. My XAML to use it looks like this:

<Setter Property="ItemsSource">
<
Setter.Value>
<
Binding
Source="{StaticResource CollectionIssuesView}"
Converter="{StaticResource IssueViewConverter}"
ConverterParameter="1000"
</
Setter.Value>
</
Setter>

As you can see, I've set it up in such a way that you can override the sorting threshold using the ConverterParameter property.

Here's the IssueViewConverter's Convert method for your reference (reformatted slightly so it doesn't take up too much horizontal space):

public object Convert(object value, Type targetType, 

object parameter, CultureInfo culture)
{
var view = value as CollectionView;
if (view == null) return value;
var threshold = parameter == null ? 1000
: System.Convert.ToInt32(parameter);
if (view.Count < threshold)
{
view.SortDescriptions.Clear();
view.SortDescriptions.Add(
new SortDescription("Title.Name",
ListSortDirection.Ascending));




view.SortDescriptions.Add(
new SortDescription("Title.Volume",
ListSortDirection.Ascending));
view.SortDescriptions.Add(
new SortDescription("Title.Year",
ListSortDirection.Ascending));
view.SortDescriptions.Add(
new SortDescription("SortOrder",
ListSortDirection.Ascending));
}
return view;
}

Is IEditableObject Too Hard?

Everyone familiar with IEditableObject? Go read about it. I'll wait.

So by now you know that IEditableObject is an interface that gives you three methods: BeginEdit, EndEdit and CancelEdit. The idea is that before you bring up the editing UI for your object you call BeginEdit, and then if the user completes the edit you call EndEdit, but if they abandon the edit (presumably by clicking Cancel on a dialog) you call CancelEdit and the changes are "rolled back".

IEditableObject works really well when your user interface is modal. If you show a modal dialog in which the user makes changes, and force them to click OK or Cancel when they're done, you know exactly when to call the methods of IEditableObject and everything is peachy.

Family.Show Screenshot But many modern applications seem to have done away with dialogs. Vertigo's awesome Family.Show is a great example of a user interface that uses docked panels to edit content, and it generally does away with the "OK/Cancel" metaphor, instead using a single "Done" button. If I screw up while editing a person, I have to undo the changes myself.

Sure, there are a few places where Family.Show uses an OK and Cancel button pair, but they're mostly about creating new objects, where the "Cancel" action isn't rolling anything back - it's just not adding the new object to the collection.

I can totally see why you'd go down this route. The "docked panel" approach is just so nice-looking, and doesn't jar the user away from the safe haven of the main window. And if I'm in the editing process and realise I'm looking at the wrong object, there's no "cancel" - I just click on the object I did want to edit, and data binding takes care of everything for me.

So ... is IEditableObject dead? Does anyone use it any more? Are modal dialogs truly going the way of the dodo?

I don't have any answers. What do you think?

Xbox 360 Service and Support

My Xbox 360 returned to me last night, and there was much rejoicing.

As Euan had suggested, there was a card offering one month's free Live subscription included, which was nice. All told the whole repair situation took less than ten days (less than eight business days) and only one phone call.

Not only that, the console I received runs way quieter than when I sent it away! I'm assuming that this is actually a new console with the same serial number sticker on it, rather than my original box. Whatever the case, it's now near-silent rather than sounding like I had an operational wind tunnel in my living room.

The only hiccup I experienced was the fact that the Xbox Live Arcade game Undertow was made free while my 360 was in Sydney getting repaired, so I was unable to download it. Today I called the support number again and explained that problem, and within about ten minutes they had credited my account with 800 MSPoints - enough to purchase Undertow (or indeed, some other game I might prefer).

So if all you read are horror stories about how bad Microsoft's support for the Xbox 360 is, consider this some good news. Sure, it sucks that I had the "red ring of death" in the first place, but honestly I'm better off because of it.

Comicster WPF Screenshots

Some scaled-down screenshots of my latest WPF version of Comicster.

Right now I can open and save files and browse around in the collection, but I can't modify the collection at all.

title issue

Some points of interest:

  • The tabs at the bottom-left represent Collection, Publishers, Creators and Characters. Switching tabs will change what the leftmost list displays.
  • The middle list is a context-sensitive list of issues. If you have clicked on a title in the collection tree, the middle list shows every issue in that title. If you click on a publisher, it'll show you every issue from that publisher. If you click on a character, it'll show every issue in which that character appears.
  • If there's no locally-cached thumbnail for an issue's cover, a "no cover art" placeholder image is shown. Double-clicking on that placeholder image will make Comicster download the image from the provided URI in a background thread, and it'll refresh automatically.

Still a long way to go:

  • Eventually the "preview" pane on the right will have to be skinnable, presumably with a new XAML-based skin system.
  • I'll also need to include the UI chrome for modifying your collection (buttons for "new folder", "new issue", "properties", "delete" etc).
  • The current version of Comicster can look up any item in an online database and upload or download its details. If comicbookdb.com or comicvine.com ever support an API (or, as I have suggested in the past, Live Clipboard) then I can ditch my own online database and use theirs.

Anyway - work progresses! It's a great learning experience, just like the first Comicster was!

SubsetCollection

I had an interesting design problem in Comicster over the weekend, and I thought I'd document my solution here.

In Comicster you categorise your trade paperbacks and titles in folders, and folders can also contain subfolders. Therefore, the Folder class has three properties: Folders, Trades and Titles, each an IList<T> (where T is of the corresponding type).

However, to ease data binding, Folder also has a property called Items, which (at first) was an IEnumerable<Item> ("Item" being the base class of Folder, Trade and Title). This means that I can bind a TreeView to the Items property and get the entire contents of that folder in one TreeViewItem.

The problem, though, is that IEnumerable<T> doesn't notify the UI when it changes. So if I add a title to a folder, my TreeView doesn't update.

I tried forcing the issue by calling NotifyPropertyChanged("Items") whenever my Folders, Trades or Titles collections changed, and that kind of worked, but the TreeView would completely repopulate and lose its SelectedItem. Ugly.

So what to do? I didn't want to make Items a normal ObservableCollection, because I wanted it to be read-only, and I like the strongly-typed approach of adding subfolders to the Folders collection, trades to the Trades collection etc. Logically the Items property had to become a ReadOnlyObservableCollection ... but how would I make it always contain the union of all three of my "real" collections?

So I struck upon an idea of defining a new class which derives from ObservableCollection, which I called SubsetCollection. When you construct it, you give it a "parent" collection, and anything that you add to this "subset" automatically gets added to the parent. Likewise, when you remove an item from the "subset", the item is removed from the parent.

The "parent" collection, in this case, is a private ObservableCollection<Item>, which is easily converted to a ReadOnlyObservableCollection<Item> for public use.

So here's my SubsetCollection class, and I'll show you some example usage code afterwards:

public class SubsetCollection<T, TAncestor> 
: ObservableCollection<T> where T : TAncestor
{ public SubsetCollection(IList<TAncestor> parent) { _parent = parent; } private IList<TAncestor> _parent; protected override void InsertItem(int index, T item) { base.InsertItem(index, item); _parent.Add(item); } protected override void SetItem(int index, T item) { TAncestor oldItem = this[index]; base.SetItem(index, item); var i = _parent.IndexOf(oldItem); if (i >= 0) { _parent[ i ] = item; } } protected override void RemoveItem(int index) { TAncestor item = this[index]; base.RemoveItem(index); _parent.Remove(item); } protected override void ClearItems() { foreach (TAncestor item in this) { _parent.Remove(item); } base.ClearItems(); } }

See what's happening? You define the class with two types - "T", which is the type of object that will be stored in this subset, and "U", from which "T" must derive, which is the type of object that the "parent" collection contains.

Any time this subset is modified, it passes that change up to the parent.

Here's a pared-down version of my Folder class so you can see what I do to make this work:

public class Folder : Item
{
    public Folder()
    {
        _folders = new SubsetCollection<Folder, Item>(_items);
        _trades = new SubsetCollection<Trade, Item>(_items);
        _readOnlyItems = new ReadOnlyObservableCollection<Item>(_items);
    }

    private ObservableCollection<Item> _items = new ObservableCollection<Item>();
    private SubsetCollection<Folder, Item> _folders;
    private SubsetCollection<Trade, Item> _trades;
    private ReadOnlyObservableCollection<Item> _readOnlyItems;

    public IList<Folder> Folders
    {
        get { return _folders; }
    }

    public IList<Trade> Trades
    {
        get { return _trades; }
    }

    public ReadOnlyObservableCollection<Item> Items
    {
        get { return _readOnlyItems; }
    }
}

So my "_folders" and "_trades" collections are subsets of the "_items" collection, which itself is made public as a read-only collection via the "_readOnlyItems" field.

Needless to say, this works a treat.

I wonder now, though, whether SyncLINQ might have taken care of this for me. Had I done a "union" LINQ query from folders, trades and titles, would SyncLINQ have kept the results up to date as each collection changed? Only one person knows for sure.

The Xbox Dies (Finally)

After experiencing intermittent freezes for a while now, my Xbox finally displayed the "red ring of death" on the weekend.

Mine was a weird situation, because my 360 only ever played up (freezing, not powering down properly) while my HD DVD add-on was plugged into the USB port. Unplugging the HD DVD player would stop the 360 from faulting, so I naturally assumed it was the HD DVD accessory at fault and not the console itself. Last week I managed to get my HD DVD player replaced by the retailer I bought it from (some 10 months later - well done Myer!) and within about 24 hours the 360 froze during a game of Oblivion.

I powered the 360 down, waited a few seconds, then turned it back on again, and pow! Three red lights - commonly known as the Red Ring of Death.

Surprisingly, the console still powers up without any problem most of the time. I've had the RRoD three times in the past two days, but nine times out of ten it starts without any problem. We've watched a few DivX videos and I've played some Carcassone and everything has been dandy.

So yesterday I rang MS support and they immediately emailed me the shipping instructions to return the 360 for repairs. I've heard good reports about the turn-around time so I'm pretty confident.

My only worry is that I will probably be without an Xbox during the week in which Microsoft is offering a free copy of Undertow in recompense for the Xbox Live downtime over Christmas. I hope I'll be able to work something out so that I can still get the free game.