Friday, December 7, 2007

MSDTC + Linq to Sql Update

When I was writing my previous article, I was keenly aware that it had it's limitations. One in particular was using an already open DataContext.

Take the following code:
// Create outside TransactionScope
var c1 = new UserDataContext();

using (var scope = new TransactionScope())
{
c1.Users.ToList();

// This will promote to MSDTC
using (var c2 = new UserDataContext())
c2.Users.ToList();

scope.Complete();
}
Since it was created outside the TransactionScope I have no way of automatically sharing these connections.

To help solve this problem (cleanly) I added a SharedConnectionScope class and a UseExistingConnection call (shown below) - both take an existing DataContext.
// Create outside TransactionScope
var c1 = new UserDataContext();

using (var scope = new TransactionScope())
using (SharedDataContext.UseExistingConnection(c1))
{
c1.Users.ToList();

// This will share existing connection
using (var c2 = new UserDataContext())
c2.Users.ToList();

scope.Complete();
}

Caveat: It only works with one 'external' connection, but that's still better than none.

You can grab the updated code here.

Thursday, December 6, 2007

Quick Application - Tickle Me Pink

colorsI do all my WPF coding in straight XAML, and for my prototypes I like to use the standard .Net colors.

So instead of playing a fun colorname -> color guessing game, I thought I'd have some fun and whip up this tiny color app (it's ridiculously easy in WPF). 

The following code is the entire application, it combines WPF, reflection, Linq and Anonymous Types.

 



UPDATE: Adjusted layout to look better in google reader.

<Window x:Class="Colors.ColorWindow" Title="Colors" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:Colors" WindowStyle="ToolWindow"
Height="500" Width="200">
<Window.Resources>
<DataTemplate x:Key="ColorTemplate">
<StackPanel Orientation="Horizontal">
<Border BorderBrush="Black" BorderThickness="1" Width="30" Height="30" Margin="10"
Background="{Binding Brush}" ToolTip="{Binding Brush.Color}" />

<TextBlock Text="{Binding Name}" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</Window.Resources>

<ListBox x:Name="colors" ItemTemplate="{StaticResource ColorTemplate}" />
</Window>
public partial class ColorWindow : Window
{
public ColorWindow()
{
InitializeComponent();

colors.ItemsSource = typeof(Brushes)
.GetProperties(BindingFlags.Static | BindingFlags.Public)
.Select(x => new {
Name = x.Name,
Brush = x.GetValue(null, null)
});
}
}

Tuesday, December 4, 2007

DataModel-View-ViewModel

WPF changed the rules for UI best practice, but it didn't update the book.

With all the new and improved DataBinding and Command features - a new set of patterns have emerged, including a recommended pattern called DataModel-View-ViewModel (DM-V-VM).

At a conceptual level this pattern looks fantastic – but there are issues... namely it doesn’t work for non-trivial scenarios.

Rather than a boring high level rant, I'll use boring examples to explain why:

Cannot support events

The recommended approach is to use DataTemplates and Commands - but DataTempates cannot handle events, and the command system is not extensive enough (eg. doesn't support mouse clicks).

Supporting events requires using code behind; which means using at least a UserControl base class.

No Keyboard support for Standard Commands

Dan Crevier and John Gossman don't mention the standard Commands, instead opting to create their own – not because it's better practice, but it's easier to demonstrate.

Their suggested approach uses CommandParameter bindings on the buttons, which only works with OnClick (i.e when the shortcut Key is pressed "null" is passed through).

Since the InputBindings.KeyBinding.CommandParameter does not support DataBinding - supporting the keyboard (and still using commands) means we can't use CommandParameters.

UI support breaks abstraction

Say that we want to delete all the selected items from a list; this means storing a list of items in the ViewModel (since we not using CommandParameters), which we then bind from our View.

But this is purely for UI logic rather than business logic!

Complicated scenarios might need multiple properties - and since the binding is not clearly defined, it will introduce bugs.

The abstraction is now broken, so let's just move our ViewModel into the code behind.

Unit testing the UI logic now not easy

No kidding, that's why we initially moved the code into the ViewModel!

All of the real logic should be implemented in the data bound objects or by a class separate to the UI. These classes are unit testable, but the UI integration is not.

Aren't we back to where we started?

Not quite, WPF's new style allows us to develop a cleaner system than the days of WinForms and MFC - and while there's not a published best practice for it, it doesn't mean that it doesn't exist.


UI programming is hard, especially since it looks so easy.

Monday, December 3, 2007

Avoiding MSDTC with Linq to Sql

Now MSDTC is not evil; it's just overkill when it isn't needed. It slows performance, increases complexity and requires client side configuration... and it can activate when you least expect it.

Take the following code:
void CreateUsers()
{
using (var scope = new TransactionScope(TransactionScopeOption.Required))
{
CreateUser("Fred");
CreateUser("Joe");

scope.Complete();
}
}

void CreateUser(string name)
{
using (var context = new UserDataContext())
{
context.Users.InsertOnSubmit(new User { name = name });
context.SubmitChanges();
}
}

This code uses the recommended (and very helpful) TransactionScope class - and unfortunately invokes MSDTC.

Since we're using separate instances of UserDataContext this creates separate database connections - and causes TransactionScope to "promote" the transaction to require MSDTC.

Avoiding this is as simple as sharing the database connection - after all, it is the same database - but passing database connections to sub methods gets ugly really quick.


My Solution

To solve this problem in a cleaner manner, I wrote a Transaction Resource Manager - which works behind the scenes and makes the above code work without change.

It simply shares database connections across the instances (only within a transaction). It's thread safe, and easy to integrate - simply change the DataContext base class in the dbml designer.



Grab the code and check it out. There's an example program and a whole slew of unit tests (around 275 - testing the various permutations of nested TransactionScopes).

Kudos to Nick Guerrea's Weak Dictionary - which I use to weakly track the transactions and share the connections.


Same Solution for other Scenarios

There are other scenarios where this problem arises:

Say you've got a database with many tables (or a plug-in system that shares a database) - a modular approach uses multiple DataContext classes.

Our problem occurs when you need to modify tables from different DataContexts within a single transaction.

Thankfully, the root cause is still the same and our solution solves these cases as well.


This has been a great learning experience for me, and I must say that the Transaction Resource Managers are very interesting (might even make a good alternate ScopeGuard implementation?)

EDIT: See updated article for extra goodness.

Wednesday, November 28, 2007

Quick Tip - Read Only Automatic Properties

This is a simple little trick, which I only discovered a few weeks ago.

In the past providing public "read only" access to a member would look something like:
private string connection;

public string Connection
{
get { return connection; }
}

With Automatic Properties in C# 3.5 the code becomes:
public string Connection { get; private set; }

The neat trick is the access modifier (private) next to the set. This allow you to internally modify the member, while publicly providing "read only" access.

Monday, November 26, 2007

VS2008 RTM Update

I have updated all the downloadable code to compile with the RTM release of VS2008.

It's not a big change, so I'll use this blog entry to update my Xceed <-> Linq code. I've fixed some minor bugs, improved performance a lot and added better linq syntax support.

So if you're using the code, it'd be a good idea to update.

Monday, November 19, 2007

IEnumerable Joy - Batch / Split

I was inspired by my good friend Nick's latest blog entry Return of the Batch Enumerable

Here he demonstrates a neat idea of using extension methods and yield to split an IEnumerable into arbitrary batches.

My version is slightly less efficient, but treats the batches as separate lazy collections - so you can use it on multiple threads etc.

I've also added a Split extension, which I'll describe - but first, the code!

static class InBatchesExtension
{
public static IEnumerable<IEnumerable<T>> InBatches<T>(this IEnumerable<T> source, int batchSize)
{
for (IEnumerable<T> s = source; s.Any(); s = s.Skip(batchSize))
yield return s.Take(batchSize);
}

public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, int items)
{
for (int i = 0; i < items; ++i)
yield return source.Where((x, index) => (index % items) == i);
}
}

The InBatches returns the same output as Nicks:

Batch: 1 2 3
Batch: 4 5 6
Batch: 7

And the Split batches the output across the collections:

Batch: 1 4 7
Batch: 2 5
Batch: 3 6

So this gives you 2 different batch splitting methods for a generic enumerable.

I love this stuff.

Tuesday, November 13, 2007

Wield the Yield

Recently I've noticed an IO pattern emerging combining yield and linq; a powerful and efficient mechanism to read data.

Check the following code: We safely open a file (with the using statement), and yield the results with a loop.
IEnumerable<string> ReadFile(string filename)
{
using (StreamReader reader = new StreamReader(File.OpenRead(filename)))
while (reader.EndOfStream == false)
yield return reader.ReadLine();
}

This simple (and beautiful) code allows us to treat a file like an array of strings - which becomes very powerful when coupled with linq.
// Contrived example - How many file lines refer to "fred"?
var result = ReadFile("file.txt").Where(x => x.Contains("fred")).Count();

I'm sure this same pattern could also be applied to other data retrieval methods, eg algorithm calculation (prime numbers, Fibonacci, etc), network communication (message queue) and even as an abstraction over asynchronous data methods.

Yield provides a lazy enumeration (doesn't execute unless needed) so the solution is generic and efficient - I like it.

Monday, November 5, 2007

n! - let me count the ways

The other day I had an interesting discrete maths assignment question involving permutations - so I decided to codify it.

"How many ways can six people (Josh, Toby, CJ, Sam, Leo & Donna) sit, if Josh must sit to the left of Leo and to the right of Sam."

Now the astute reader will immediately recognize the answer to be 2 * (4! + 3!3!) = 120; but to be sure I wanted to double check this via C#. (I'm keen to redo this in F# too)

My solution was a quick hack, and is by no means "the best way" - but using linq it sure looks pretty.

class Program
{
static IEnumerable<List<string>> Permutate(IEnumerable<string> people,
IEnumerable<string> current)
{
// Get remaining people and recurse
foreach (var person in people.Where(x => current.Contains(x) == false))
foreach (var result in Permutate(people, current.Concat(new string[] { person })))
yield return result;

if (current.Count() == people.Count())
yield return current.ToList();
}

static void Main(string[] args)
{
string[] people = new string[] { "Josh", "Toby", "CJ", "Sam", "Leo", "Donna" };

var result = Permutate(people, new string[] { }).ToList();

// Josh sits to the left of Leo
var Josh_Leo = result.Where(r =>
r.FindIndex(x => x == "Josh") < r.FindIndex(x => x == "Leo"));

// Josh sits to the right of Sam
var Sam_Josh = Josh_Leo.Where(r =>
r.FindIndex(x => x == "Sam") < r.FindIndex(x => x == "Josh"));

var count = Sam_Josh.Count();
}
}

This simple example shows why I'm a such fan of linq in C# - the pre-linq code for this certainly wouldn't be as eloquent.

Oh, and it also shows why I'm a fan of maths... it's much more efficient to just to calculate the factorials.

Update: Formatting code in a blog sure is a pain!

Tuesday, October 30, 2007

F# is so Passé

Lately I've been trying to juggle learning a mix of technology. WPF, .net 3.5 (linq), maths, F#... Sometimes I feel like I have Internet Multitasking Syndrome.

Although Internet Multitasking Syndrome is not a known medical disorder (I just made it up five minutes ago), it is not uncommon for people to become so immersed in their online activities that their cognitive abilities wane.

After hours starring at a screen, flipping between web pages and information outlets, people can develop a feeling of anxiety, stress and a decrease in mental performance, said John Suler, author of The Psychology of Cyberspace.

"There are limits to how much information one person can process," he continued.


I started learning about a little known language called F# a couple of months ago, where I read most of the Foundations of F# book over a rather intense week.

Since then I've dropped the ball... there's just too much to learn within our software field.

I'm keen to get back into it, as F#'s functional principles are very appealing to me. There's a sense of power and elitism playing with such a language. It's close to it's mathematical roots, and has the potential to create highly concurrent systems.

These things are addictive for software engineers. Power and elitism - it's why C/C++ are so popular and why VB programmers get no respect.


Now that F# is an official MS language, it's becoming quite popular. While this is fantastic for the language - a small selfish part of me wants to keep it for myself. I don't want it to become 'common' and spoilt by countless bad programmers writing spaghetti code.

Unfortunately this also includes me - so to avoid becoming an Italian Chef, I'm planning to read Structure and Interpretation of Computer Programs during my holidays. I've heard this is a classic book covering functional programming (in scheme).

Wish me luck!

Wednesday, October 10, 2007

Death Trap

When I first started riding my motorbike I became much more aware of my environment... and not in a pleasant way. After coming out of my metal cocoon (car), everything became a threat and I felt fully exposed to the world.

It's with good reason too; I live in beautiful Queensland where every week 1 rider dies and 15 are injured. And I don't need a maths degree to know that the statistics are against me.

Even still I love riding my bike, it got me out of my comfort zone and I have a new perspective, and a new sense of freedom and opportunity.

So here comes the clichéd analogy to programming.... Our comfort zone is our greatest death trap.

Our industry moves far too quickly learn everything, so it's an easy trap to become stagnant with familiar technology.

We've all been victim's of stagnancy at some point, but tragically some developers spiral down until they feel so far behind there's no point playing catch up.

Then they're stuck working with an obscure, unsupported technology - or they get promoted into management.

Others are trapped by their language of choice. I met a guy just recently who, with great passion, thought 'C' was the language for everything. Web apps, database apps... everything.

I felt for this guy, because I've been there before... and it's utter madness.


It takes effort and it's painful to learn new things. There's also a high risk that what you learn is completely redundant... but while it's important to pick your technology carefully - it's better to learn something than nothing at all.

My challenge is to never stop learning; it's not without risk or effort - but the rewards of freedom and perspective are invaluable.

Tuesday, October 2, 2007

I don't want to be a Maths Teacher

Before I started my maths degree I braced myself for the inevitable question "why maths?"

That's okay, maths isn't everyones favorite subject - but as it turns out the more popular question is "do you want to be a Maths teacher?"...

No!

Don't get me wrong, I have no problems with teaching, in fact it might be cool to be a lecturer one day... but it makes me sad that people think learning maths is only good for teaching maths.

It's like the definition of Recursion: see Recursion; a tragic cycle of futility; a perpetual motion machine that affects nothing and goes nowhere.

No!

I want to shout out from the roof tops - don't people realize that maths is the basis of all technology and human advancement?

Economically, math brings order to chaos. The steady job, the home (or mortgage), even food on the table and clothes on our backs - thank maths. Too melodramatic? Google the Great Depression sometime.

Math heals us when we are sick. Statistical drug trials determine what medicine works, mathematical models of the human body are used by doctors and physiotherapists to determine better techniques for recovery.

I won't even get started on computers or civil construction.

Above all, maths is eloquent, philosophical and beautiful. It changes your perceptions and makes you appreciate everyday life even more.

</rant>

Thursday, September 27, 2007

Updatable, inheritable, WPF bounded Linq queries

This is part 4 of my "binding Linq to Xceed's data grid" blog series; however I've changed direction dramatically.

Skipping the details, heres the code binding to a linq query:

users.LinqContext = new UserDataContext();

users.ItemsSource = from i
in users.DataSource<User>()
select i;


And this code fully supports inserts/updates/deletes.

The implementation lives inside the DataSource<User>() call. This devious character returns a reference to a IBindingList (which supports the table modifications) and implements IQueryable (to support linq queries).


What about inheritance?

Imagine you had a sub class called SuperUser; if you've played with linq inheritance you'll know that you have to use the base type User to actually do anything. It's kind of a pain, and you get real friendly with the .OfType<>() call.

So here's the code again, this time selecting all SuperUsers.


users.ItemsSource = from i
in users.DataSource<User, SuperUser>()
select i;


Can I use .Take(x)?

As far as I can tell, all the standard linq statements are supported (including aggregate operators). I haven't looked into partial classes and anonymous types, though I doubt they'd work well.


I won't go into the laborious details of how it's all implemented, just know that it's been fun playing with linq expression trees and writing my own IQueryProvider.

If you are interested, the code can be found here.

I haven't seen anything quite like this out there, so if you have some opinions - I'd love to hear some feedback.

Monday, September 24, 2007

Linq Table and GetNewBindingList()

While I'm talking about binding linq data tables to WPF, I should mention the simplest method, namely Table.GetNewBindingList();

This method allows you to add/insert/update (even with Xceed's grid) quite easily, but does not save implicitly, ie. you have to manage it yourself.

If you prefer to batch up all your changes and save en mass at a special point (this is a common UI pattern) - then this might be a great solution for you.


One issue with with approach however, is that it only supports the whole table, ie. not based on queries. This might be fine if you are using the WPF's data filters, but it's not an optimal result with large amounts of data.


I'm planning to investigate these two aspects in the near future, and hopefully I'll find an elegant solution.

Friday, September 21, 2007

Linq with Xceed's WPF Grid - Part III - Hooking up the Delete

One of the under appreciated features of WPF is its Command support. This feature allows you to hook up events in a more abstract and loosely coupled way; with a great collection of common actions provided by default.

To hook up delete functionality from Xceed's data grid to a Linq data table, I took advantage of these Command gems and as you will see, they make things very easy to use.

The provided ApplicationCommands.Delete command, comes with a localized string ("Delete") and associated key bindings ("Del" Key).

Handling this command in the LinqGrid is as simple as calling the following in the initialization routines:

CommandBindings.Add(new CommandBinding(ApplicationCommands.Delete,
OnDeleteCommand, OnCanDeleteCommand));


Implementing the OnCanDeleteCommand to return true, if any items are selected and the OnDeleteCommand to delete the selected items, and it's done! Well almost.

Automatically deleting the selected items (with the "Del" key) without any warning is usually not the best behaviour, so I implemented a RoutedEvent called PreviewDelete, which allows you to show a message box and/or cancel the delete.

Show me the XAML

Another great benefit of using Commands is the ability to bind other UI elements as the action co-coordinator for the command. i.e Buttons, Context Menus, etc.

Not only is this clean and easy, but it also has built in routines to control the IsEnabled state. ie. Button is disabled if you cannot currently delete.


<Button Command="Delete"
CommandTarget="{Binding ElementName=users}"
Content="{Binding Command.Text, RelativeSource={RelativeSource self}}" />


The "Command" is quite simply a reference to the ApplicationCommands.Delete command, while the "CommandTarget" is the name I gave to my LinqGrid.

The unfortunately long "Content" attribute is the Buttons label, bound to the Command itself. Remember how I said the provided commands have localized names... this is how you access them in XAML. Thankfully, this is also purely optional.

This is all you need to do. When the button is pressed, the Command is fired and our LinqGrid performs the delete, first checking with PreviewDelete for its permission.

Download the sample solution for the full code.

Linq with Xceed's WPF Grid - Part II (and a half)

An excellent suggestion was raised from my last post (thanks Marcus), which is to make the Linq DataContext a property on the LinqGrid.

This way the LinqRow can access it via it's parent, rather than via the singleton (which is bad practice in my book).

I've put all this code in a solution (includes sample database and all), so I'll let the code speak for itself.

Download Sample Solution

Thursday, September 20, 2007

Linq with Xceed's WPF Grid - Part II

In my first post I showed a handy binding class that wraps around your linq data tables, now I'm going to show some handy changes to Xceed's data grid, to complete the linq binding.

My main problem with the data grid, is there isn't any good place to commit a transaction after editing a row.

To fix this, we can provide our own DataRow class which handles the SubmitChanges() when a row is dirty.

Update: Modified code to use IsDirty flag. Note that IsDirty is reset to false in base.EndEdit().


class LinqRow : DataRow
{
public override void EndEdit()
{
if (IsDirty == true)
DataSource.Context.SubmitChanges();

base.EndEdit();
}
}


To make the DataGridControl aware of our new DataRow class, we need to derive and override the GetContainerForItemOverride() method.

class LinqGrid : DataGridControl
{
protected override DependencyObject
GetContainerForItemOverride()
{
return new LinqRow();
}

protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);

if (View == null)
{
View = new TableView();
AdjustHeadersFooters();
}
}

private void AdjustHeadersFooters()
{
// Show / hide the element base
View.FixedHeaders.Clear();
View.Headers.Clear();

// Add a ColumnManagerRow
DataTemplate columnTemplate = new DataTemplate();
columnTemplate.VisualTree =
new FrameworkElementFactory(typeof(ColumnManagerRow));
View.FixedHeaders.Add(columnTemplate);

// Add the insertion row
DataTemplate insertTemplate = new DataTemplate();
insertTemplate.VisualTree =
new FrameworkElementFactory(typeof(InsertionRow));
View.FixedHeaders.Add(insertTemplate);
}
}



Insertion Row

You may have noticed the AdjustHeadersFooters call in the class above, this code removes the GroupBy control and adds in the Insertion row by default. The GroupBy control is cool, but I rarely use it.

Putting it together

Instead of using the DataGridControl in your xaml file, simply use the LinqGrid.

In my next few posts I'll discuss hooking up the delete, sorting and filtering, and how to use the linq queries instead of the whole table.

Linq with Xceed's WPF Grid

Binding a read only Linq data table to Xceed's WPF data grid couldn't be easier, but things get a little trickier when you want insert/delete/update functionality.

The general recommendation (from Xceed's samples) is to implement a derived IBindingList collection class to provide the behaviour yourself.

Sounds like a lot of work to do something simple, especially if you want to bind to a lot of different objects - so here's a generic one I've prepared.

BTW: I haven't seen any articles on the web regarding best practice with this, so I'd love any comments if there is a better way.



class LinqList<T> : BindingList<T>
{
ITable table = null;

public LinqList(ITable table)
: base(table.OfType<T>().ToList())
{
this.table = table;
}

protected override object AddNewCore()
{
T item = (T)base.AddNewCore();

if (table != null)
table.Add(item);

return item;
}

public override void EndNew(int itemIndex)
{
base.EndNew(itemIndex);

if (itemIndex >= 0)
DataSource.Context.SubmitChanges();
}

protected override void RemoveItem(int index)
{
if (table != null)
table.Remove(this[index]);

base.RemoveItem(index);
}
}


My first code draft uses the BindingList as a base class (to avoid implementing everything myself) and takes a Linq data table as a constructor parameter.

Notice the OfType() call in the constructor, this provides basic support for inheritance with Linq, but more on that in a later post.

I use a singleton to store my Linq data context (DataSource.Context) to call SubmitChanges() after adding a new item.



static class DataSource
{
static DataSource()
{
DataSource.Context = new MyDataContext();
}

static public MyDataContext Context { get; set; }
}


Binding to Xceed

Simply bind an instance of this class to your data grid, and you're almost set!

See Part II for some changes that need to be made to the Xceed grid, to make this binding easier.