Hilton Giesenow's Jumbled Mind

the madness that is...

News

This is my little spot in cyberspace where you will find a collection of random (but mostly software-related) thoughts and ideas that are frightening in their shining brilliance (or something like that ;->).
 
Please enjoy your stay and feel free to Contact Me.
 
Microsoft MVP
 
I'm a Shoe Circus Member!

.Net Links

BlogRoll

Misc. Links

Syndication

Shoe Circus vs. New Family

Well I watched Shoe Circus earlier this week, and I must admit I didn't get it all, despite being a Seinfeld fan. I watched New Family this morning though and it was excellent! If you're a fan of either Bill Gates or Jerry Seinfeld, check them out.

Winforms JS Minifyer

For Tech Ed recently I did a talk on ASP.NET performance and scalability, and one of the topics we discussed was minifying JavaScript, which basically means getting rid of all of the comments, whitespace, etc. There are a couple of tools out there that do this, probably the most popular of which is Douglas Crockford's JSMin. The only problem is that it's a console app (which is great for automated builds, but not as good for demo'ing on stage). So, I wrote a small winforms wrapper around JSMin, which you can download here: Visual JavaScript Minifier.

In case you're still now sure what it is, here's a screenshot:

Screenshot

Visual Studio eXtensibility (VSX) Video - How Do I: Create a Basic Language Service Using the Managed Babel System?

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:

Screenshot

Logging LINQ To SQL Queries

I posted recently on logging the LINQ To SQL output to the ASP.NET response stream. Damien Guard has an even better post on logging to all kinds of places, including multiple writers.

Validation Method Timing in LINQ To SQL

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.

Posted: Aug 07 2008, 09:47 PM by hiltong | with 2 comment(s)
Filed under: ,
Generating Enums From Database Tables

 

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 = tableNamesIdea;
string idColumnName = idColumnNamesIdea;
string valueColumnName = valueColumnNamesIdea;

#>
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
}

}

Using Enums With LINQ To SQL

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:

AddingColumn

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.

AddingColumnToEntity

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:

ChangeEnumType

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.
Posted: Aug 06 2008, 02:40 PM by hiltong | with 3 comment(s)
Filed under: ,
SQL Server 2008 RTMs Today!

Wow, a fresh announcement at Tech Ed South Africa for a change - apparently SQL Server 2008 RTMs today :-)

For Open Source: LAMP; For MS: ...

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!? :->

Tech Ed South Africa 2008

I'm putting the finishing touches on my sessions for Tech Ed South Africa next week. If you haven't booked yet, there are still some places, it seems, so book now (good luck getting flights from C.T. though!)

I'll be giving a couple of sessions this year, so I hope to see you there. My breakout sessions are:

  • WEB303 - Performance and Scalability in ASP.NET Development
  • DEV310 - Understanding LINQ To SQL
  • SOA203 - Introduction to Windows Workflow Foundation

And I'll be giving the following Chalk 'n Talks:

  • CNT230 - Developing Solutions with LINQ To SQL – Lessons From The Trenches
  • CNT234 - Practical Code Generation With Microsoft's T4 Engine

The full agenda for Tech Ed is at http://www.teched.co.za/agenda.aspx. There are a lot of sessions this year, so it should be a bumper event.

Visual Studio eXtensibility (VSX) Video - How Do I: Add Code Snippets to My Language Service?

In this VSX How Do I Video, we look at how to add Code Snippet functionality to your language service.

For reasons unbeknownst to me, MS have not yet posted the actual initial video on Language Services in 2008 yet *->.

Screen shot for code snippets:

How to add Code Snippets

Visual Studio eXtensibility (VSX) Video - How Do I: Add Intellisense to a Language Service?

In this video, I cover how to add Intellisense functionality to your custom language service. The video covers Statement/Word Completion and QuickInfo. I can see this coming to a LOLCode Language Service near you!

Here's a screen shot:

Screenshot

Visual Studio eXtensibility (VSX) Video - How Do I: Work With Other Combo Box Types?

I've been a bit bogged down, so I haven't noticed some of the recent Visual Studio eXtensibility (VSX) How Do I videos going live. I see that How Do I: Work With Other Combo Box Types? is now available. It's a follow on to an earlier video which covered adding a standard combo box, and it includes adding an Indexed Combo, a Most-Recently Used (MRU) Combo (like the Find combo in Visual Studio) and a Dynamic Combo (Like the Zoom combo in most PDF viewers).

Here's a screenshot:

Screenshot

Displaying LINQ To SQL's Actual SQL Queries in your ASP.NET Page

I've made use of the Log property on the DataContext class in a few of my LINQ To SQL posts. Usually, it's been in a console application, and we're just looking at the SQL output in the console window, so we use:

dataContext.Log = Console.Out;

However, in a web application, this won't help. If you want to see the output of your SQL directly in the page, you can use:

System.IO.StreamWriter httpResponseStreamWriter = new StreamWriter(HttpContext.Current.Response.OutputStream);
dc.Log = httpResponseStreamWriter;

As to whether it's a good idea to display this directly into the output (effectively Response.Write) - that's up to you ;->. As an alternative, as Log is just expecting a TextWriter, you could use a StringBuilder with a StringWriter, and then display it's output in a label.

For a more robust solution, Kris Vandermotten has a sample on Sending the LINQ To SQL log to the debugger output window.

Posted: Jul 16 2008, 10:54 AM by hiltong | with 1 comment(s)
Filed under: ,
Reminder - Brad Abrams on MVC

Just a reminder that Brad Abrams will be visiting us and giving a talk for SA Dev on ASP.NET MVC.

Final event details:

Date: 25th June, 2008
Time: 18:15 for 18:30
Venue: Microsoft Cape Town (Please note the address)
            Golf Park 3, Engen House, Raapenberg Road, Mowbray

Also, please RSVP if you haven't done so already

More Posts Next page »