Visual Studio LightSwitch 2011 May Bridge the Gap

Microsoft announced recently that Visual Studio LightSwitch 2011 will be released on July 26. I’ve been watching the development of this product with keen interest for the last year or so. I’m looking forward to evaluating it more in-depth soon.

Building common line-of-business (LOB) applications in today’s enterprise development stacks can be too complex and too costly for today’s tight budgets. For this reason alone there are “literally millions” (exaggeration license: 02389-872.159-034) of LOB applications being created by non-programmer Office users. These “applications” most often get pushed around in Excel via Exchange. Many live in a hastily created Access database and shared clumsily and un-securely on a workgroup file server.

Still others are somewhat more sophisticated and are hosted on products such as QuickBase from Intuit. This latter category resolves many of the problems inherent in the emailed Excel spreadsheet and the Access fileshare such as security, reliability, common user interface, ease of use, etc. There are many more specialized web-based SaaS offerings that solve specific business problems. One notable vendor who led the way in this area is 37 signals.

But these solutions are not always enough to meet the needs of the business. There is a gap between these “entry-level” (ELOB) applications and what I will call primary line-of-business (PLOB) applications. The PLOB is a custom developed, sophisticated enterprise application with complex business rules, sometimes even more complex user interfaces, and far more complex data and integration requirements, upon which the business relies for its core service offering or mission critical systems.

Somewhere between ELOB and PLOB there has to be a middle ground. Let’s call it the mid-line-of-business (MLOB) application (FLA creator license: FOLK-LANG-MAKE-UPPR-WXYZ). There are plenty of “app generator” and scaffolding tools that claim to live in the MLOB space. I’ve never been too impressed with them. They always seem to lose their way in convention, diverging from business requirements too greatly to meet business needs.

So I am hopeful that LightSwitch will fill the MLOB gap. We’ll see. Time will tell. In any case, it should at least be fun to find out.

Winning Teams Have Winning Coaches

How many games will an NFL team win if the coaching staff and the owners remain in the locker room during practices and games, coming out only at half time and between quarters to ask the team members what they can do to win the game?

ESPN’s Worst NFL teams of all time include:

#1. 1976 Buccaneers (0-14)
It was their season debut. They were shut out five times and averaged fewer than nine points per game. Defensive lineman Pat Toomay said, “The coach stopped talking to us after the third game. During the week, he wanted nothing to do with us.”

… (You can read more on the page linked above. I’ve included snippets here of the two that I felt illustrated my point.) …

#9. 2001 Carolina Panthers (1-15)
”The energy has been sucked out of our organization and our fan base,” said owner Jerry Richardson, after firing head coach George Seifert at the end of the year.

Great players cannot win consistently without great coaches. The same is true of software development teams, or any other type of team for that matter. If the coaches remain in the locker room, the team, being paid professionals, will still play, and they might even score, and with ideal conditions, they might even deliver a win or two, but a losing season can be guaranteed when the coaches and owners can’t be bothered to be a part of the game.

On the other hand, we have great examples such as Vince Lombardi who went to work for the Packers and turned a 1-10-1 in 1958 team into one of the greatest teams in the game and with five NFL championships before he left nine seasons later. He was in the game. He was a motivational leader. He was a great coach.

Or how about Tom Landry and his goofy hat who coached the Cowboys for 28 years and had a 20 year winning season streak. He was a great coach.

This list of winning coaches is long. Only the losing players on a losing team remember their losing coaches beyond the losing season. Winning coaches are remembered and revered long after they’ve left the field.

And how many games do you think those winning coaches missed?

Who was your greatest coach? And why? I want to hear from you.

SQLite on Visual Studio 2010 Setup Instructions

Obsolete

Go to the new SQLite on Visual Studio with NuGet post instead.


Be sure to read upgrade instructions I've just posted as a follow-up to this post.

I’m just starting to play with SQLite and the System.Data.SQLite library created by Robert Simpson and taken over by the SQLite.org folks. In attempting to get things working in Visual Studio 2010, I ran into a few issues, so this post is as much a reminder for myself as it is a help for other .NET developers who wish to use SQLite from within Visual Studio 2010.

The current binary installers from sqllite.org for the System.Data.SQLite .NET assembly do not include the Visual Studio designers or the ADO.NET driver required for use of SQLite in the Server Explorer. So here’s the winning combination I’ve found for getting my environment set up properly.

  1. Download and install version 1.0.66.0 from sourceforge.net because current binary installs on SQLite.org at system.data.sqlite.org do not include the Visual Studio designer or ADO.NET driver install.
     
  2. Download and install the latest versions (x86 and x64) from system.data.sqlite.org (currently 1.0.73.0 which contains the SQLite 3.7.6.3 engine).
    Important Note: If you have Visual Studio 2008 and 2010, be sure to choose both when prompted as I found reports from others who had problems otherwise.
     
  3. Copy the x86 binaries into and overwriting file at C:\Program Files (x86)\SQLite.NET\bin (assuming you used the default install location for version 1.0.66.0 and you're running x64 Windows). And if you are on an x64 box, copy the x64 binaries to the C:\Program Files (x86)\SQLite.NET\bin\x64 directory, overwriting existing files.

Now you can open Visual Studio 2010 and navigate to the Server Explorer, right-click the Data Connections node, choose Add Connection and click the Change button for Data source. You can then select the SQLite Database file source like this:

dsource

Click the new button and navigate to your desired directory and supply a file name and you’ll end up with something like this:

dconn

With a new data connection, you can use the table designer, but it has limitations and it’s probably not the best approach with an embedded database engine from a development perspective anyway, since generally you’re going to want your app to be able to create the database from script embedded in code.

So now all that’s left to get started writing code against your database is to add your references like this:

dref

And since Entity Framework supports SQLite, you can add your ADO.NET Entity Data Model to your project and it will produce a nice connection string like this for you (VB-like line _ breaks added):

<connectionStrings>
  <add name="testEntities"
    connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl| _
    res://*/Model1.msl;provider=System.Data.SQLite; _
    provider connection string=&quot;data source=C:\Code\Projects\test.db&quot;"
    providerName="System.Data.EntityClient" />
</connectionStrings>

or a non EF 4 connection string of

<connectionStrings>
  <add name="mytest"
    connectionString="data source=C:\Code\Projects\test.db;"
    providerName="System.Data.SQLite" />
</connectionStrings>

Now remember, model first is not currently supported, so you need to create your data and then update your model from data. You also need to make sure that you add the following to your config file or you’ll get a nasty runtime error:

<startup useLegacyV2RuntimeActivationPolicy="true">
  <supportedRuntime version="v4.0" />
</startup>

UPDATE (30 minutes later) Just a bit more testing reveals that I missed one step. Very important to know and use.

First, I reinstalled the x86 and then x64 latest installs and checked the checkboxes to install to the GAC and modify the path. Then I ran “test” from the command line and after modifying the connection string by giving the file a path like C:\temp\test.db, the tests ran fine. Looking at the chm help file and the test.exe.config revealed the trick I needed.

The 1.0.66.0 install adds a factory reference to your .NET machine.config file like this:

</DbProviderFactories>
  ...
  <add name="SQLite Data Provider"
    invariant="System.Data.SQLite"
    description=".Net Framework Data Provider for SQLite"
    type="System.Data.SQLite.SQLiteFactory,
      System.Data.SQLite,
      Version=1.0.66.0,
      Culture=neutral,
      PublicKeyToken=db937bc2d44ff139" />
</DbProviderFactories>

While this entry makes the Data Connection and designer possible, it will cause you problems when trying to run using the latest 1.0.73.0 referenced assemblies until you add this to your own config file:

<system.data>
  <DbProviderFactories>
    <remove invariant="System.Data.SQLite" />
    <add name="SQLite Data Provider"
      invariant="System.Data.SQLite"
      description=".Net Framework Data Provider for SQLite"
      type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
  </DbProviderFactories>
</system.data>

Next step: experiment with updating my machine.config in its many incarnations to point to the latest and greatest x64 version 1.0.73.0 with token db937bc2d44ff139 like this:

</DbProviderFactories>
  ...
  <add name="SQLite Data Provider"
    invariant="System.Data.SQLite"
    description=".Net Framework Data Provider for SQLite"
    type="System.Data.SQLite.SQLiteFactory,
    System.Data.SQLite,
    Version=1.0.73.0,
    Culture=neutral,
    PublicKeyToken=db937bc2d44ff139" />
</DbProviderFactories>

Note that this will move the machine.config reference to the MSIL (Any CPU) version rather than the x86 version. For my machine, this means making changes in (and remember to open as Administrator so you can save the file):

C:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.config
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\CONFIG\machine.config
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config

Rebooting, just to be paranoid.

And now, run the same test after commenting out the local app.config’s <system.data><DbProviderFactories> node and everything works as expected. No more bad image exception. And the Data Connection designer continues to operate as expected. Now on to some real coding.

Windows 8 Preview Elevates Touch and HTML 5 and JavaScript

In a press release from Redmond today, we get a little preview of what is to come with Windows 8 and it is HTML 5 and JavaScript.

I have mixed emotions about all of this. Some may say that it’s like putting lipstick on a pig, but in fact I don’t think Windows 7 is a pig at all. It beats any other desktop OS, bar none, and no, I don’t want to hear it from the Mac crowd (see my previous post). For me, it feels like putting an enhanced Windows Phone 7 wrapper on the desktop OS. This is great news for the upcoming Windows 8 tablet user and market. For me, for now, it feels like my phone UI is getting in the way of my desktop UI. I’ll probably get used to it later, but for now it just feels strange.

In any case, the press release and the little demo video seems to answer three primary and critical questions. Here are my first impressions and a few key frames from the video to tease you into watching it.

What is a Windows 8 App?
Based on this press release and quick demo, we can assume that a “Windows 8 App” is a touch enabled HTML 5 and JavaScript application running locally on the IE 10 engine. This seems to directly integrate IE technology into the OS. I wonder if Eric Holder will care. I assume that if I can still make another browser my default, we’ll all be safe from the clutches of the U.S. Justice Department.

start
The touch enabled Start Desktop

What is Windows 8?
Aside from assumed improvements in the kernel, driver infrastructure, etc., we learn from this demo that the primary target UI is the touch interface with cool split thumb-friendly touch keypads for all platforms. Of course support for the 20th century input devices formerly known as the keyboard and mouse continues to be available. Behind the new touch enabled "Start screen" with smart app tiles, the old "Start button and menu" and desktop interface can be found underneath the covers. So you can have your touch-cake and eat your mouse and keyboard driven app-cake too. Smart.

start2
Dragging the next desktop pane into view. Note the distinctly non-Windows 8 Word icon.

What Should a Developer Know About Windows 8?
In addition to your bag of tricks you currently maintain, you'll need to add HTML 5 and JavaScript if you don't already have them. And if you are not already learning HTML 5 and getting past the 'alert' statement/method in JavaScript, you are standing on the dock and the boat is hoisting anchor. Get with it. Buy some books. Watch some tutorials. And start writing your own "Hello Touch World" Windows 8 App now.

tweetsheet
Tweet in your Windows 8 App while balancing the budget in your mundane Excel spreadsheet.

It will be fun to watch this latest incarnation absorb some of the best of its competitive predecessors. It will be more fun to read about their indignation. It will be less fun if Microsoft prematurely releases and we have a Vista-like PR disaster regardless of the basic goodness due to a few unpolished bits. Either way, I’m heading back to my HTML 5 and JavaScript study group.

The Gaping Hole in Mac User’s Sense of Self

HaHa! HaHa! HaHa! HaHa! HaHa! Ha!

macmac

To the Mac community, all I can say is, will you now please SHUT UP about your “secure” OS.

Welcome to the real world of being a target and having to take measures to protect yourself. Now that you have realized your security was never security but obscurity, perhaps we can all have an adult conversation about battling the bad guys together instead of us having to listen to you crow about your false sense of superiority.

Four Functions for Finding Fuzzy String Matches in C# Extensions

How similar are these two strings? Does string X sound like string Y? Could they be duplicates? Is the difference between string N and string M just a typo? There are many scenarios in enterprise software development where the answers to these questions can be highly significant.

In my search to answer such questions with code, the most helpful resource I’ve ever found was presented by George M. Brown on www.codeguru.com who implemented four well known and powerful fuzzy string matching algorithms in VBA for Access a few years ago. In an effort to convert these algorithms to C#, I found two alternatives that saved me some time (see below).

The four algorithms, with requisite Wikipedia links, are:

Each of the algorithms have been implemented here as extensions to the string and string array. Before we get to the code, let’s take a look at some results. Here are two very simplistic tests. The algorithms are not combined in any way. You can experiment with them and create your own secret sauce. 

Name Matching for (mispelled deliberately): "Jensn"
The first test result set presents the raw output of the algorithms on a mispelled surname (mine) against a list of other surnames. I’ve highlighted the best score.

Dice Coefficient for Jensn:
    .00000 against Adams
    .46154 against Benson
    .00000 against Geralds
    .37500 against Johannson
    .42857 against Johnson
    .76923 against Jensen
    .30769 against Jordon
    .30769 against Madsen
    .00000 against Stratford
    .14286 against Wilkins

Levenshtein Edit Distance for Jensn:
    4 against Adams
    2 against Benson
    5 against Geralds
    5 against Johannson
    3 against Johnson
    1 against Jensen
    4 against Jordon
    4 against Madsen
    8 against Stratford
    6 against Wilkins

Longest Common Subsequence for Jensn:
    .04000, s against Adams
    .33333, ensn against Benson
    .05714, es against Geralds
    .08889, jnsn against Johannson
    .17143, jnsn against Johnson
    .56667, jensn against Jensen
    .06667, jn against Jordon
    .13333, en against Madsen
    .02222, s against Stratford
    .11429, ns against Wilkins

Double Metaphone for Jensn: ANSN
    ATMS metaphone for Adams
    PNSN metaphone for Benson
    JRLT metaphone for Geralds
    AHNS metaphone for Johannson
    ANSN metaphone for Johnson
    ANSN metaphone for Jensen
    ARTN metaphone for Jordon
    MTSN metaphone for Madsen
    STTR metaphone for Stratford
    FLKN metaphone for Wilkins

Address Matching for "2130 South Fort Union Blvd."
The second test is the same code run against multiple addresses trying to match a given address. Let’s see how it turned out.

Dice Coefficient for 2130 South Fort Union Blvd.:
    .16000 against 2689 East Milkin Ave.
    .10000 against 85 Morrison
    .27273 against 2350 North Main
    .07843 against 567 West Center Street
    .66667 against 2130 Fort Union Boulevard
    .61538 against 2310 S. Ft. Union Blvd.
    .42553 against 98 West Fort Union
    .12245 against Rural Route 2 Box 29
    .05000 against PO Box 3487
    .04444 against 3 Harvard Square

Levenshtein Edit Distance for 2130 South Fort Union Blvd.:
    18 against 2689 East Milkin Ave.
    22 against 85 Morrison
    18 against 2350 North Main
    22 against 567 West Center Street
    11 against 2130 Fort Union Boulevard
    8 against 2310 S. Ft. Union Blvd.
    14 against 98 West Fort Union
    19 against Rural Route 2 Box 29
    22 against PO Box 3487
    22 against 3 Harvard Square

Longest Common Subsequence for 2130 South Fort Union Blvd.:
    .02116, 2 st in v. against 2689 East Milkin Ave.
    .02020,  son against 85 Morrison
    .04444, 230 oth in against 2350 North Main
    .01010,  st t  against 567 West Center Street
    .25481, 2130 fort union blvd against 2130 Fort Union Boulevard
   .25765, 230 s ft union blvd. against 2310 S. Ft. Union Blvd.
    .25514,  st fort union against 98 West Fort Union
    .02593,  out  o  against Rural Route 2 Box 29
    .01347, o o  against PO Box 3487
    .01389, 3 hrvd against 3 Harvard Square

Double Metaphone for 2130 South Fort Union Blvd.: STFR
    STML metaphone for 2689 East Milkin Ave.
    MRSN metaphone for 85 Morrison
    NRTM metaphone for 2350 North Main
    SSNT metaphone for 567 West Center Street
    FRTN metaphone for 2130 Fort Union Boulevard
    SFTN metaphone for 2310 S. Ft. Union Blvd.
    STFR metaphone for 98 West Fort Union
    RRLR metaphone for Rural Route 2 Box 29
    PPKS metaphone for PO Box 3487
    RFRT metaphone for 3 Harvard Square

As you can see, the double metaphone algorithm may not be as useful on its own as the other algorithms. But when you put them together in creative ways, you’ll get a very powerful result.

Here’s how easy the algorithms, as extension methods, are to use.

private static void NameMatching()
{
	//name matching
	string input = "Jensn";
	string[] surnames = new string[] { 
		"Adams",
		"Benson",
		"Geralds",
		"Johannson",
		"Johnson",
		"Jensen",
		"Jordon",
		"Madsen",
		"Stratford",
		"Wilkins"
		};

	Console.WriteLine("Dice Coefficient for Jensn:");
	foreach (var name in surnames)
	{
		double dice = input.DiceCoefficient(name);
		Console.WriteLine("\t{0} against {1}", 
			dice.ToString("###,###.00000"), name);
	}

	Console.WriteLine();
	Console.WriteLine("Levenshtein Edit Distance for Jensn:");
	foreach (var name in surnames)
	{
		int leven = input.LevenshteinDistance(name);
		Console.WriteLine("\t{0} against {1}", leven, name);
	}

	Console.WriteLine();
	Console.WriteLine("Longest Common Subsequence for Jensn:");
	foreach (var name in surnames)
	{
		var lcs = input.LongestCommonSubsequence(name);
		Console.WriteLine("\t{0}, {1} against {2}", 
			lcs.Item2.ToString("###,###.00000"), lcs.Item1, name);
	}

	Console.WriteLine();
	string mp = input.ToDoubleMetaphone();
	Console.WriteLine("Double Metaphone for Jensn: {0}", mp);
	foreach (var name in surnames)
	{
		string nameMp = name.ToDoubleMetaphone();
		Console.WriteLine("\t{0} metaphone for {1}", nameMp, name);
	}
}

Source References
In researching and finding these algorithms, I poured over what seemed like hundreds of articles, blogs and open source resources. In the end, I settled on three primary sources and made certain modifications to suite my own needs. Here they are.

Additional references:

I recommend you spend time with these sources and doing your own research. Undoubtedly you will come up with even better algorithms. When you do, please share them with us here.

Update: code now on GitHub

Try Catch Nothing Worst Code Ever

Tracking down a problem in a commercial .NET library today, I found this little gem (identifying code in the try removed):

try
{
   //any code that could fail in any way here
}
catch (Exception)
{
}

Not only should this construct not compile, any attempt to do so should cause your computer to explode.