Unfortunately the out-of-the-box implementation of WPF’s TextBox control has no built-in way to execute a ‘default’ ICommand action when the Enter key is pressed. I took a first stab at this for my current client, and here is a rewritten/improved implementation of a “Commandable” TextBox:
/* Copyright (c) 2009 Giorgio Galante.
* Released under the MIT License (http://en.wikipedia.org/wiki/MIT_License)
*/
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
namespace WPFControls
{
public class CommandableTextBox : TextBox
{
public static readonly DependencyProperty
CommandProperty = DependencyProperty.Register(
"Command",
typeof (ICommand),
typeof (CommandableTextBox),
new UIPropertyMetadata(null));
public static DependencyProperty CommandParameterProperty =
DependencyProperty.Register(
"CommandParameter",
typeof (object),
typeof (CommandableTextBox),
null);
public CommandableTextBox()
{
KeyUp += KeyUpAction;
}
public ICommand Command
{
get { return (ICommand) GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public object CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
private void KeyUpAction(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
if (Command != null)
{
BindingExpression be = GetBindingExpression(TextProperty);
if (be != null)
{
be.UpdateSource();
}
Command.Execute(CommandParameter);
}
}
}
}
}
I'm not entirely sure how Microsoft can explain this one. The disconnected user experience with TFS (all versions, including the upcoming 2010) is absolutely terrible. For source control, there's absolutely no reason to even require an online/offline mode. CVS, SVN and the like don't care if they are connected to your source code repository during file-editing operations (for purposes of flagging a file as 'checked out'.)
It's very common for large corporations to setup VPN systems without a split-tunnel capability - meaning that all network traffic has to go through their VPN, and thus is usually very slow. In scenarios such as this one, a developer would likely prefer to log into the VPN, get latest, log out of the VPN, do 0..N hours of work, log back into the VPN, get latest, check-in, and so on.
My biggest complaint about having to go over my client's VPN tunnel for all track is not a 'big brother'/privacy/I-want-to-surf-the-dark-corners-of-the-web-while-working issue, it's that voice/video calls in Office Communicator R2 (the company's IM client) are very low quality compared to when making direct connections to their internet-facing messaging servers. Is this TFS's fault? Not directly of course. But if it weren't so adamant about being connected during file-check-out operations, I wouldn't bother with the VPN for 90% of my day.
Shame on Microsoft for neglecting this problem for so long (5 years and counting.)
This post is about the 3rd reason I would not recommend using Microsoft’s Entity Framework 4: We Can’t wait for Microsoft to build the features we want, when there are other inexpensive or free solutions already out there.
Simply put, there are better, more mature, products out there than EF4. If you’re building a simple desktop To-Do List application with SQL CE – then by all means, use EF (as long as you don’t want to use Identity keys/server-generated values, because that’s not supported.) It’s free, it comes with .NET, etc. But if you’re building a real enterprise application that doesn’t fit into Microsoft’s neat Entity Framework feature-set, don’t even risk it.
One of my client’s developers has been looking at replacing our initial ORM selection (LLBLGen Pro) with Entity Framework 4. We are still at a very early stage in development, with little time/money invested in the ORM layer – switching will not be an expensive proposition. We’re using the model-first approach (i.e. start off designing the conceptual model and then it will generate your database schema.) We seem to be doing a lot of T4 Self-Tracking entities template modifications, of which I am not a fan of. Particularly because once we make a change to a vendor-provided template, we are stuck supporting it. The whole point for using an ORM is that it should be a highly configurable black-box. You should only have to customize the black box when dealing with edge-case scenarios. This doesn’t seem to be the case - the developer charged with the evaluation / migration to EF is a smart & seasoned developer – I don’t believe he’s just diving into template customization for ‘fun’. During this dive into EF4, we also discovered that the Entity Framework’s Model-First (using Self-Tracking Entities?) approach does not support the SQL Server timestamp type. Maybe it’s a bug, maybe it’s a feature on their to-do-list. Either way – it’s another sign that Entity Framework 4 is not mature enough.
By default, EF4 has Lazy Loading turned on for new EDMX models. We’re using Self-Tracking entities, which means we don’t want lazy loading (because it will cause massive queries to be issued when the entities are serialized and sent over the wire to our WCF client) – so now we need to turn it off every time we spin up a new database context. In my mind this is a general design flaw of the framework. Lazy loading & disconnected scenarios (in which Self-Tracking entities are necessary) are meant for two very different styles of application development. Yet they’ve mashed up the behavior into a single database context object. I am very biased by my experience with LLBLGen Pro – its approach seems to make more sense to me - you have two ways to set up your project: you can either use Self-Service approach(which allows for lazy loading, etc.) and then there’s the Adapter approach (centralized fetches.) These are very explicit boundaries – as I believe they should be. Microsoft has completely muddied the waters with its decision to change behavior based on which version of the Entity Framework the model started from.
These are only a few examples of many that highlight how the Entity Framework team took on way too much, way too soon – without really understanding the problems they should have been trying to solve for other developers. Their vision does not seem to line up with what the rest of the ORM world is doing (who else has a Conceptual –> Physical model? in v1?) Who asked for this feature? In theory (and in an ivory tower) it sounds great. In practice they spent a lot aof time building a mapping system, designer, and a runtime to support this mega-feature. What they should have been doing is building an ORM that had fewer moving parts, that behaved like its would-be real-world users expected. Maybe I don’t understand the Entity Framework team’s vision.
All I know is that I wanted a wrench, and Microsoft gave me a 20-tool multi-tool that doesn’t work as well as the simple wrench I already have.
For version 5, the Entity Framework team should get out of their ivory tower, go out to customers’ sites who've chosen NOT to use Entity Framework and see what they’re using, why and how they’re using it and incorporate these ideas into the next version.
Let’s talk about the second reason to stay away from the Microsoft Entity Framework 4.
We can’t trust Microsoft to maintain backwards compatibility with (or future support of) previous versions of the Entity Framework.
Microsoft freely admits that they made a big mistake with Entity Framework v1. So how do they rectify the situation? By easily letting you upgrade your EF v1 project/model to EF v4, but completely changing the default behavior of the runtime. I’m talking about the “new” Lazy-Loading feature Microsoft added to EF4 – it is turned on by default. You can turn it off by altering the way you instantiate your context – have fun finding every instance of where you instantiate your context (we all know you should use a factory or DI container do this for you – but Microsoft makes a huge assumption here – that most people don’t just ‘new up’ their database contexts.)
I mentioned in the first post of this series that Microsoft is finally adding N-tier support in the Entity Framework. That’s only partly-true. The Entity Framework itself will not have self-tracking entities (typically required for N-Tier development) – this feature will be delivered in an out-of-band release. I’m very apprehensive about being dependent on a Microsoft out-of-band release because time and time again, Microsoft drops support for these projects once they’ve moved on to bigger & better things. Edit: 12/1/09 - As Danny Simmons commented below, the Self-Tracking Entities will be included in the .NET Framework 4 RTM. This is good news. Fortunately or not, your choice of ORM technology will affect and touch almost every part of a typical enterprise application.
Microsoft’s poor track record in this space likely means yet another do-over at some point – and you don’t need to psychic to know how that story ends for teams that have chosen EF.
In this post I’ll expand on the first major reason that the Entity Framework version 4 is still inadequate for enterprise-grade use.
We as architects & software developers need to build software that works today.
If you’re doing new development with Visual Studio 2010 Beta 2 / .NET 4.0 for a system to be released after the RTM date (March 22nd 2010), you might think that the Entity Framework v4 would be a great candidate for your ORM layer. It’s part of the .NET Framework so there’s little, if any political or (initial) financial cost to using it within an organization. In my experience as a consultant, introducing enterprise customers to ORM (the concept), and making them comfortable with a 3rd party ORM solution takes a significant effort.
Unfortunately there are major shortcomings to the Entity Framework 4 that still make it risky to select it as your ORM solution. The designer for EF is still far from being reliable. In my own personal project (in a quest to learn more about EF4), I’ve found it to lose entities (inexplicably will not import tables into the model) causing me to have to delete the model and recreate it from scratch. This leads me to not changing the names of the association/foreign-key properties because I would lose those name changes when I update the schema & recreate the EF4 model, so we have ‘ugly’ names for association/foreign-key properties such as Foo.Bar1 Foo.Bar2. I have also seen it fail to make necessary changes to its model after a schema update. In one instance I made a foreign-key column nullable, updated the Entity Framework model and yet when trying to persist I still received an error about the required foreign key mapping. After a bit of digging I found the multiplicity of the foreign-key/association was still set to “One” instead of “Zero to One”. If they still can’t get these simple “kinks” worked out, how confident can we be with the code that is ultimately responsible for saving & retrieving our company’s most important information on a daily basis?
Against my own opinion, my current client is planning to use EF4 for a global enterprise application with several thousand users. I believe we’ll eventually hit one or more brick walls and go back to the solution we chose at the project’s inception.
For my personal EF4 “learning” project, I’m using SQL CE 3.5 because the application is meant for single users. Having spent most of the last several weeks working on the UI (WPF/MVVM), I had created most of the data by hand via SQL Scripts. All of my EF interactions to date (until yesterday) had been reading data – never thinking there would be significant problems writing data. The first problem was Foreign Keys – how could I set a foreign key without having the foreign entity? Typically, most ORMs provide the foreign key field so you can set it directly i.e.:
1: orderLineItem.OrderId = 12345;
2: orderLineItem.StatusId = 67890;With EF4 you have the following two options:
1. Query the database for the foreign key entity and attach it to the associated entity like so:
1: var orderLine = DB.Models.OrderLine.CreateOrder( apple );
2: orderLine.OrderReference.Attach(
3: (from o in db.Order where o.Id == 12345
4: select o).First());
5: orderLine.StatusReference.Attach( ( from s in db.OrderStatus where s.Id == 67890
6: select s ).First());
7: db.SaveChanges();The major shortcoming of the above code is we are forced into querying the database for information we already have, just to play by the EF’s rules. This is an unacceptable approach.
2. Use the “Reference” concept:
1: orderLine.OrderReference = new System.Data.Objects.DataClasses.EntityReference();
2: orderLine.OrderReference.EntityKey = new EntityKey(“Entities.Orders”, “Id”, 12345);
The primary issues for the above code are:
Both of these options are overly complex and too verbose. Is this how other popular ORMs (nHibernate, LLBLGen, etc.) do it? Not even close. I’ll dig deeper into this theme later in major reason #3 (We Can’t wait for Microsoft to build the features we want, when there are other inexpensive or free solutions already out there.)
The Dealbreaker
The straw that finally broke the camel’s back was when I was ready to call SaveChanges() and have my entity persist to the SQLCE 3.5 database. I was perplexed to find out why my application blew up, the underlying EF exception read:
System.NotSupportedException: Server-generated keys and server-generated values are not supported by SQL Server Compact.
I thought to myself, I’m not doing anything out of the ordinary – my tables all have integer identity primary keys. Surely Microsoft couldn’t have neglected to make CE Identity keys work in EF4. They certainly did, not once but twice. People complained about this missing “feature” in EF v1 and here we are still waiting for a solution. Had I known from the beginning this would never work (say from the designer being smart enough during the schema import/update process to warn me about it), I would have taken an alternate approach (i.e. not use EF4, or use GUIDs for keys.)
Regardless of what Microsoft says about the EF4 being good enough and the ADO.NET Entity Data Model designer being fixed, it’s not ready for use in building tomorrow’s applications – not even close. I should note that the Entity Framework 4 is still in beta (#2). Having said that, I’ve not seen any indication that Microsoft is going to fix any of the issues I’ve mentioned here (or the issues I’ll be following up with in the next 2-3 posts.)
It's common for Microsoft to deliver a substandard 1.0 product, a mediocre 2.0 version and eventually by the time 3.0 comes along, they've delivered a something decent. Let's look at Microsoft's long history in the ORM space:
2001 - ObjectSpaces was to be a great addition to the .Net ecosystem. Somewhere between 2001 and 2005, Microsoft integrates ObjectSpaces with WinFS: the mother of all query technology. In 2005 the entire WinFS project is shelved, taking our ObjectSpaces dream with it.
2007 - LINQ to SQL would save the day (but only if you were using SQL Server.) After much hype, and barely a year after it RTM’d, Microsoft announced in October of 2008 that LINQ to SQL was dead. The Entity Framework is proclaimed to be the future of .NET data access technologies.
2008 - Entity Framework v1.0 makes it's glorious debut. And it's unanimous - it is not what developers wanted or asked for. Too many bugs, limitations, missing features, and lack of support for n-tier development.
2009-2010 - Entity Framework v4.0 (or v2.0, but who's counting anyway.). Still missing features, and still buggy designer (as of Beta 2.) We finally get n-tier support by way of self-tracking entities.
This timeline clearly shows Microsoft has a terrible track record in delivering and supporting an object-relational mapping technology. I maintain the vote of no confidence for the Entity Framework as a whole, given that we, the enterprise architects & developers:
In my next post I'll provide details on the shortcomings of the Entity Framework v4.0.