August 2008 - Posts
My latest VSX How Do I Video is on how to build a language service using the Managed Babel infrastructure. A Language Service is the infrastructure that allows Visual Studio to provide editing for your language, like Intellisense, syntax colouring, etc. (See Language Service Essentials for more) Managed Babel is a set of starting points to help build your own language service (see Babel Package Overview for more).
The full video can be found at How Do I: Create a Basic Language Service Using the Managed Babel System?. Here's a screenshot for a simple C-style language:

The LINQ To SQL designer-generated classes contain 3 different ways to implement validation based on property values. Two of these are internal, in the form of partial methods, and one is external in the form events on the domain classes themselves. However, the timing around these differs slightly, so I'm going to examine them according to the timing.
To look into these approaches, I'm using the Customers table from Northwind. I've got it on my LINQ To SQL designer, and I've implemented the following additional partial class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
public partial class Customer
{
partial void OnCityChanging(string value)
{
if (value == "Cape Town")
throw new Exception("Not in my town!");
}
partial void OnCityChanged()
{
if (this.City == "Johannesburg")
throw new Exception("What are you doing up there?!");
}
}
}
In this class, you can see that I'm validating the "city" property both before and after it is set. What is important is that this validation code will fire directly during the property setter on the domain class. For instance, an exception will be thrown for both of the following two cases:
Customer c = new Customer();
c.City = "Cape Town";
and
Customer c = new Customer();
c.City = "Johannesburg";
and in fact the validation is roughly equivalent in terms of timing because both of these methods are called during the property setter, as the following code snippet from the designer-generated code show:
[Column(Storage="_City", DbType="NVarChar(15)")]
public string City
{
get
{
return this._City;
}
set
{
if ((this._City != value))
{
this.OnCityChanging(value);
this.SendPropertyChanging();
this._City = value;
this.SendPropertyChanged("City");
this.OnCityChanged();
}
}
}
Of course, this also implies that validation outside of the Customer class structure (i.e. using the PropertyChanging or PropertyChanged events, fired via the SendPropertyChanging and SendPropertyChanged methods, respectively) will occur at the same. As a point of common sense, I would recommend doing the validation in the "changing" methods because then the value has not yet in fact been set and the change can be effectively "rolled back".
In contrast to the above approach, it is possible to subsume all of your validation logic into one place and implementing the OnValidate partial method, as follows:
partial void OnValidate(System.Data.Linq.ChangeAction action)
{
if (this.ContactName == "Hilton Giesenow")
throw new Exception("He's too young for Northwind!!");
}
But this method has two important points of interest. First off, it allows you to potentially control the type of change that is occurring in the database (via the ChangeAction enumeration, which has values of None, Insert, Update and Delete). In addition, the timing is quite different on this method - it only fires as part of the final SubmitChanges method call on the datacontext - i.e. when the database call is about to be made. If you are creating a new instance, for instance for an Insert, and setting the properties just before the call to SubmitChanges, the difference in timing between these two approaches is basically academic. However, if you are creating a new Customer and setting properties as part of a series of UI operations for instance, and only planning to make the SubmitChanges database call at a later stage, this difference is of some importance.
I would suggest that the safest approach is to combine the two by moving the actual validation logic out into a separate method (to keep it DRY, of course) and calling it from both places, like so:
partial void OnValidate(System.Data.Linq.ChangeAction action)
{
ValidateCity(this.City);
}
partial void OnCityChanging(string value)
{
ValidateCity(value);
}
partial void OnCityChanged()
{
ValidateCity(this.City);
}
protected void ValidateCity(string value)
{
if (value == "Cape Town")
throw new Exception("Not in my town!");
else if (value == "Johannesburg")
throw new Exception("What are you doing up there?!");
}
(I know I've removed the ContactName validation and replaced it with the ValidateCity call in the OnValidate - I was trying to illustrate the consolidated approach).
This approach doesn't cover the external clients, but this sort of validation should be internal to the class anyway.
For an different angle on this stuff with some great additional areas of coverage, check out Simple Validation with LINQ to SQL Classes by Beth Massi.
I posted earlier about how to use enums in LINQ To SQL, and I spoke about why I think enums are useful. The only problem with this approach was that you had to create the enums by hand, even if you had the same data sitting in a lookup table. If you were at my recent Code Generation with T4 Chalk 'n Talk at Tech Ed South Africa, you would have seen me generate enums automatically from the database, which is what we're going to do below.
Note: If you're not familiar at all with T4, check out this post on T4 Templates.
<#@ template language="c#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Data" #>
<#@ import namespace="System.Data" #>
<#@ import namespace="System.Data.SqlClient" #>
<#
string tableName = "CustomerTypes";
string idColumnName = "CustomerTypeID";
string valueColumnName = "Value";
#>
using System;
namespace ConsoleApplication1
{
public enum <#= tableName #>
{
<#
SqlConnection sqlConn = new SqlConnection(@"Data Source=.\sqlexpress;Initial Catalog=TaskList;Integrated Security=True");
sqlConn.Open();
string sql = string.Format("SELECT {0}, {1} FROM {2} ORDER BY {0}", idColumnName, valueColumnName, tableName);
SqlCommand sqlComm = new SqlCommand(sql, sqlConn);
IDataReader reader = sqlComm.ExecuteReader(CommandBehavior.CloseConnection);
System.Text.StringBuilder sb = new System.Text.StringBuilder();
while (reader.Read())
{
sb.Append("\t\t" + reader[valueColumnName] + " = " + reader[idColumnName] + "," + Environment.NewLine);
}
sb.Remove(sb.Length - 3, 3);
sqlComm.Dispose();
sqlConn.Dispose();
#>
<#= sb #>
}
}
The template above will generate an enum like the following:
using System;
namespace ConsoleApplication1
{
public enum CustomerTypes
{
Good = 0,
Bad = 1,
Ugly = 2
}
}
There are two drawbacks with the template above though. The first is that it uses the table name for the enum name, which means the enum might be a plural if you follow the table-names-as-plurals convention, whereas I only make an enum a plural if it is a flag (i.e. it can contain a combination of values). A lot of people don't follow the same conventions, so I'm not going to try solve this issue here.
The second, and more important, problem is that the template above means you need to have a copy of it for each lookup table in your database that you want to create an enum from. I've amended the template to cater for multiple, specific tables instead and to put these into one file. The new version appears below:
<#@ template language="c#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Data" #>
<#@ import namespace="System.Data" #>
<#@ import namespace="System.Data.SqlClient" #>
<#
string[] tableNames = { "CustomerTypes", "TaskTypes" };
string[] idColumnNames = { "CustomerTypeID", "TaskTypeID" };
string[] valueColumnNames = { "Value", "Value" };
#>
using System;
namespace ConsoleApplication1
{
<#
SqlConnection sqlConn = new SqlConnection(@"Data Source=.\sqlexpress;Initial Catalog=TaskList;Integrated Security=True");
sqlConn.Open();
for (int i = 0; i < tableNames.Length; i++)
{
string tableName = tableNames
;
string idColumnName = idColumnNames
;
string valueColumnName = valueColumnNames
;
#>
public enum <#= tableName #>
{
<#
string sql = string.Format("SELECT {0}, {1} FROM {2} ORDER BY {0}", idColumnName, valueColumnName, tableName);
SqlCommand sqlComm = new SqlCommand(sql, sqlConn);
IDataReader reader = sqlComm.ExecuteReader();
System.Text.StringBuilder sb = new System.Text.StringBuilder();
while (reader.Read())
{
sb.Append("\t\t" + reader[valueColumnName] + " = " + reader[idColumnName] + "," + Environment.NewLine);
}
sb.Remove(sb.Length - 3, 3);
reader.Close();
sqlComm.Dispose();
#>
<#= sb #>
}
<#
}
sqlConn.Dispose(); #>
}
and it will generate a set of enums like this:
using System;
namespace ConsoleApplication1
{
public enum CustomerTypes
{
Good = 0,
Bad = 1,
Ugly = 2
}
public enum TaskTypes
{
Bug = 0,
Task = 1,
Enhancement = 2
}
}
I don't know about you, but I'm quite a fan of using Enumerations (Enums) in my apps. I'm all for more readable, more explicit code because I think it helps a lot with maintainability, and enums help with that. I'd much rather read a line of code that says:
customer.CustomerType = CustomerType.Good;
than
customer.CustomerType = 1;
Of course, it means you also get Intellisense when you're writing the code. Another advantage is that enums, which are usually lookup types and very often bound to controls like comboboxes, will come down as part of the schema for your web service, negating calls to get the values.
So how can we make use of enums in LINQ To SQL? Actually, it's pretty easy.
Step 1: Create The Enum
This part should be familiar, as it's just a standard enum. I'm going to be working with Northwind and adding a CustomerType enum. Mine appears as follows:
public enum CustomerType
{
Good = 1,
Bad = 2,
Ugly = 3
}
Step 2: Add The New Column To Customers
The next step is to add the new column to your Customers table. In the database, just add it as a regular integer column:
Note: you can add an actual table into your database to hold these types as well, like a CustomerTypes table, but it's not strictly necessary. I would recommend doing so though and adding a foreign key reference to the Customers table, as it helps for things like reporting straight off your database.
Once you've done this, you'll need to add the property to your LINQ To SQL domain object. You can do this on the designer by dragging the new field onto an empty space on the designer. You'll get a duplicate copy of Customer ("Customer1" probably), then you can cut and paste the property onto the original entity. Obviously, you only need to do all this if you have an existing entity you're adding to.
The next step is critical. By default, the Type will come up as an "int (System.Int32)", but you can change it to the fully-qualified type of the enum (in my case, ConsoleApplication1.CustomerType). BUT, in order to locate it fully, you have to add the global identifier, as follows: global::ConsoleApplication1.CustomerType , so type that as is (but the equivalent for your namespace) into the textbox, as below:
That's it! You should now be able to use enums in your code directly, like we saw at the beginning. What's also cool is that you can now use them in your LINQ To SQL queries as well, like:
var customers = from c in dc.Customers
where c.CustomerType == CustomerType.Good
select c;
UPDATE: Here's a post on how you can generate the enum classes automatically from your database tables.
Wow, a fresh announcement at Tech Ed South Africa for a change - apparently SQL Server 2008 RTMs today :-)
I'm sure many of you have heard about a very common open source acronym: LAMP. If you haven't, it's an acronym for Linux, Apache, MySQL and PHP. MS doesn't seem to have a nice acronym for its stack, but at the same time it's got some new and emerging technologies that I think are going to be a very powerful triad of tools. These are:
1) LINQ To SQL - what can I say, I'm clearly a fan. I haven't spent all that much time with Entity Framework, but I've seen that not everyone is happy with it (see this no confidence vote for instance. Make sure to read Microsoft's response too though). I have a feeling that LINQ To SQL may come to outstrip E.F. in terms of uptake (aside from the fact that it's been released earlier, but also because it's more simple).
2) WCF - It's the best communications stack MS has, and it's going to be around a while, as far as I can see. It may depend on how Astoria (ADO.Net Data Services) plays out though...
3) Silverlight (specifically 2.0). The story around finally being able to build .net cross platform UIs in the browser - what more can I say.
So, with this, I propose the new Microsoft stack acronym - LWS (pronounced 'Lewis'). Who's with me!? :->