garyshort.org


I am a Technical Evangelist for Developer Express, my work blog is here but this one is more fun. :-)

November 2007 Entries

DDD6 Pictures

Thanks to some of my "friends" there is now a fair collection of terrible pictures of me at DDD6 hanging around Facebook. I've posted them here for your... erm, entertainment.

n580259551_440258_2559 n580259551_440277_8997 n580259551_440285_1868

 n716528319_195188_1421 n716528319_195190_1984n716528319_195221_1047

 n716528319_195222_1342

Technorati tags: , ,

The Singleton Pattern - Just for the Record

If you are using the .Net framework (version 3.0 for sure, I've not checked the specs of the others but I can't believe its different) and you want to implement the singleton pattern then

public sealed class MySingleton
{
    private MySingleton() { }
    public static readonly MySingleton Instance = 
new MySingleton(); }

Is all you need; the framework will handle lazy initialization and thread safety for you. You don't need a lock with double check and all that GOF goodness, that was back in the days of C++, those days are gone now, embrace the framework and feel the .Net love :-)

DDD6 a Review

So how was DDD6 from my point of view? Well I have to say it was excellent, as always. For me, there are three stand out presenters that attend these conferences; Oliver Sturm , Guy Smith-Ferrier and Dave McMahon, I like to ensure I catch these guys. First session of the day Oliver was up with his business apps with WPF, this was a good talk aiming to take the audience's knowledge past the basics. Oliver checked with the audience and since the majority hadn't really come across WPF before, he spent this session covering the introductory content. Next I was in my own session - I kind of felt I had to be there - which is just as well really, because if I hadn't of had to have been there, I would have struggled to decide between Chris Hay's Silverlight and Paul Lockwood's CruiseControl.Net presentations. My session went okay I felt, and the feedback I've had so far has been positive, but there was a delay in getting started that meant the end of the presentation was a little rushed and not as clear as I'd have hoped. Following this, I attended Guy's Astoria presentation. What can I say? Guy's a presenting star in my book and this talk was another master class. The information that Guy presented was up to date, clearly explained and just what I needed to know as an introduction to Astoria. After lunch I sat in on Colin Mackay's recruitment presentation. I wasn't sure what to expect from this non technical session, but it turned out to be very informative and it held my attention more than I thought it would. I finished off the day by attending James Winter's presentation on how to write a Facebook application. I'm not sure what attracted me to this presentation, but I wasn't disappointed. It was something different to look at and rounded off the day nicely. All in all it was a cracking day. If you fancy attending the next one, then keep an eye on the Developer Day site as registration tends to fill up fast.

The Community Evangelist’s Creed

In tribute to my fellow community evangelists, and with a hat tip to the Rifleman's Creed, I give you the Community Evangelist's Creed.

Developer Day Scotland

If the previous post has whetted your appitite for community conferences then you'll want to know that a call for speakers for Developer Day Scotland was announced at DDD6. If you fancy speaking then give it a go! For those of you who just want to attend then the agenda and speaker list will expand as the call is answered. The conference is on the 10th May 2008 and I hope to be speaking there myself. This is a fantastic opportunity to see some great speakers north of the border. Hope to see you there!

The Community Evangelist’s Creed

This is my laptop, there are many like it but this one is mine. My laptop is my best friend. It is my life. I must master it as I must master my life. Without me, my laptop is useless. Without my laptop I am useless. I must run my laptop true. I must present to my audience who are trying to appraise me. I must educate them before they appraise me. I will! My laptop and myself know that what counts in this presentation is not the slides we show, the words we use, or the jokes we tell. We know that it is the education that counts. We will educate! My laptop is human, even as I, because it is my life. Thus, I will learn it as a brother. I will learn its weaknesses, its strengths, its parts, its accessories, its screen and its keyboard. I will ever guard it against the ravages of travel and damage as I will ever guard my legs, my arms, my eyes and my heart against damage. I will keep my laptop patched and ready. We will become part of each other. We will! Before God I swear this creed. My laptop and myself are the educators of our audience. We are the masters of our technology. We are the saviours of my presentation... So be it, until education is ours and there is no more audience, but education! With a hat tip to the Rifleman's Creed.

Home From DDD6

Hi gang, I'm back from Developer Day at TVP in Reading; it was another cracking conference, so well done to Craig Murphy and the guys responsible for organising it all. Good job! As I promised in my presentation you can download the code samples and slide deck for my Patterns talk here. I also mentioned that you should check out my blog if you wanted to see an implementation of the ActiveRecord pattern that serialised objects to a database. I have two implementations, one serialising an object that maps to a single table, and one that demonstrates how to handle a parent-child relationship using transactions. Just to close, if you attended any sessions at DDD6 this year, don't forget to go and fill out the feedback form on the site. The guys read everyone and use them to ensure that the next one will be even better.

Service Factory

The latest version of the Service Factory has been released by the Microsoft Patterns and Practices Team.
The Web Service Software Factory: Modeling Edition (also known as the Service Factory) is an integrated collection of resources designed to help you quickly and consistently build Web services that adhere to well-known architecture and design patterns. These resources consist of patterns and architecture topics in the form of written guidance and models with code generation in the form of tools integrated with Visual Studio 2005.
Find out more about the factory here. Technorati Tags: ,

Design Patterns Talk

Last night I gave a talk on design patterns to the North East Scotland .Net User Group. The talk went well and if you were there then thanks for coming. As I said, I'll be putting the slides and code examples up here over the week-end, so if you'd like them, check back here later.

Update: As promised, you can now download the slidedeck and code from my design patterns talk from here. Note, the code examples are written with VS 2008; oh, and if you are planning to come and see the talk at Developer Day, no reading ahead. :-)

Technorati Tags:

Microsoft Gives Away Search Server 2008

Microsoft said that it's giving away Search Server 2008 Express to anyone who wants it, just by downloading it directly from Microsoft's Web site here. The Express version is the sibling to the enterprise-strength version of Microsoft Search Server 2008, which the company debuted at an enterprise search conference in San Jose, Calif.
More...

Design Patterns #7.2 - Active Record

Back here, I said the next time I wrote about the Active Record Pattern I'd show you how to handle parent and child relationships. So here we are. The first thing we are going to need is a SQL Server 2005 Express database to play in, so let's create one...

CREATE DATABASE ActiveRecord
go
USE ActiveRecord
go

Now, let's create minimalist Parent and Child tables...

CREATE TABLE Parent
(
    ParentId
        INT
        NOT NULL
        IDENTITY(1,1)
        PRIMARY KEY CLUSTERED,
    Tag
        VARCHAR(20)
        NOT NULL
)
go

CREATE TABLE Child
(
    ChildId
        INT
        NOT NULL
        IDENTITY(1,1)
        PRIMARY KEY CLUSTERED,
    ParentId
        INT
        NOT NULL
        REFERENCES Parent(ParentId),
    Tag
        VARCHAR(20)
        NOT NULL
)
go

And to finish, we need create and read stored procedures...

CREATE PROCEDURE CreateParent
    @Tag VARCHAR(20)
AS
    INSERT INTO Parent VALUES (@Tag)
    SELECT scope_identity()

go

CREATE PROCEDURE CreateChild
    @ParentId INT,
    @Tag VARCHAR(20)
as
    INSERT INTO Child VALUES (@ParentId, @Tag)
    SELECT scope_identity()

go

CREATE PROCEDURE ReadParentAndChildrenById
    @ParentId INT
AS
    SELECT
        p.ParentId,
        c.ChildId,
        p.Tag AS [Parent Tag],
        c.Tag AS [Child Tag]
    FROM
        Parent p
        inner join Child c ON p.ParentId = c.ParentId
    WHERE
        p.ParentId = @ParentId

go

Now that we have our demo database set up we need to add our handy little stored procedure for reflecting on the database...

CREATE PROCEDURE GetParamsForStoredProcNamed
    @storedProcName VARCHAR(256)
AS

SELECT
    c.name AS ParameterName,
    t.name AS Type
FROM
    sysobjects o
    INNER JOIN syscolumns c ON o.id = c.id
    INNER JOIN systypes t ON c.xtype = t.xtype
WHERE
    o.type = 'p' AND
    o.name = @storedProcName 

go

Finally, what we need to do is amend our implementation of the ActiveRecord class from last time to be able to handle the creation of parent and child rows in the table. To do this we simply add the ability of the class to use and enlist transactions. The code below should be well enough commented for you to follow but if not leave a comment on this post. N.B. this code is written in C# 3.5 using Visual Studio 2008 Beta 2.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Data;
using System.Reflection;
using System.Configuration;

namespace garyshort.org.patterns.ActiveRecord
{
    abstract public class ActiveRecord
    {
        private SqlConnection _conn = null;
        private SqlTransaction _transaction = null;
        private Object lockObj = new object();

        public void StartTransaction()
        {
            //GS - Create a connection
            _conn = new SqlConnection();
            _conn.ConnectionString = 
                ConfigurationManager.ConnectionStrings[
                        "ConnString"].ConnectionString;

            _conn.Open();

            //GS - Create a transaction
            _transaction = _conn.BeginTransaction();
        }

        public void RollBackTransaction()
        {
            if (_transaction == null)
            {
                throw new Exception("No current transaction!");
            }

            _transaction.Rollback();
            _transaction = null;
            _conn = null;
        }

        public void CommitTransaction()
        {
            if (_transaction == null)
            {
                throw new Exception("No current transaction!");
            }

            _transaction.Commit();
            _transaction = null;
            _conn = null;
        }

        public SqlTransaction GetCurrentTransaction()
        {
            return _transaction;
        }

        public SqlConnection GetCurrentConneciton()
        {
            return _conn;
        }

        public void Create(
                SqlTransaction currentTransaction,
                SqlConnection currentConnection)
        {
            //GS - Set the connection and transaction 
            //values and call Create()
            _transaction = currentTransaction;
            _conn = currentConnection;
            Create();
        }
        public void Create()
        {
            //GS - By convention this method calls the
            //CreateObjectName stored procedure so we
            //need to reflect on the database to find
            //out what parameters that stored proc takes
            using (SqlCommand reflectionCmd = new SqlCommand())
            {
                string procName = "Create" + this.GetType().Name;

                SqlConnection conn = new SqlConnection();
                reflectionCmd.Connection = conn;

                reflectionCmd.Connection.ConnectionString =
                    ConfigurationManager.ConnectionStrings[
                        "ConnString"].ConnectionString;

                reflectionCmd.Connection.Open();

                reflectionCmd.CommandText =
                    "GetParamsForStoredProcNamed";

                reflectionCmd.Parameters.AddWithValue(
                    "@storedProcName", procName);

                reflectionCmd.CommandType =
                    CommandType.StoredProcedure;

                SqlDataReader reflectionDr =
                    reflectionCmd.ExecuteReader();

                //GS - Now we know what params the stored proc takes
                //we can fill it with the object properties which, by
                //convention, will be named the same as the params.
                //Reflect on the object to fetch the property values
                using (SqlCommand createCmd = new SqlCommand())
                {
                    string paramName = String.Empty;
                    object paramValue;
                    while (reflectionDr.Read())
                    {
                        //GS - Get the parameter name and add it if
                        //its not there already. Remember the
                        //parameter name from the stored procedure
                        //reflection will have an @ before it, so we
                        //have to substring past it.
                        paramName = reflectionDr.GetString(0);
                        if (!createCmd.Parameters.Contains(
                            paramName))
                        {
                            paramValue = this.GetType().InvokeMember(
                                paramName.Substring(1),
                                    BindingFlags.GetProperty, null,
                                        this, null);

                            createCmd.Parameters.AddWithValue(
                                paramName, paramValue);
                        }
                    }

                     //GS - Now all we have to do is execute the
                    //stored proc

                    //GS - Set up a command object...
                    createCmd.CommandText = procName;
                    createCmd.CommandType =
                        CommandType.StoredProcedure;

                    //GS - and a connection object...
                    createCmd.Connection = _conn;

                    //GS - and a transaction...
                    createCmd.Transaction = _transaction;
                    
                    //GS - Execute the command...
                    int newId =
                        Convert.ToInt16(createCmd.ExecuteScalar());

                    //GS - Assign the new Id to the object.
                    object[] args = { newId };
                    this.GetType().InvokeMember("Id",
                        BindingFlags.SetProperty, null, this, args);
                }

                reflectionCmd.Connection.Close();
            }
        }

    }

    public class Parent: ActiveRecord
    {
        public int Id { get; set; }
        public string Tag { get; set; }
        public List<Child> Children { get; set; }

        public Parent()
        {
            Children = new List<Child>();
        }
    }   

    public class Child : ActiveRecord
    {
        public int Id { get; set; }
        public int ParentId { get; set; }
        public string Tag { get; set; }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            //GS - Let's test out the ActiveRecord

            //GS - Create a new Parent
            Parent p = new Parent();
            
            //GS - Set its tag value
            p.Tag = "Parent 1";

            //GS - Start a transaction
            p.StartTransaction();

            try
            {
                //GS - Save the Parent to get an Id
                p.Create();

                //GS - Add children
                for (int i = 0; i <= 5; i++)
                {
                    Child c = new Child();
                    c.ParentId = p.Id;
                    c.Tag = "Child " + i.ToString();
                    p.Children.Add(c);
                }

                //GS - Save children, enlist the current transaction
                foreach (Child c in p.Children)
                {
                    c.Create(
                        p.GetCurrentTransaction(),
                        p.GetCurrentConneciton());
                }

                //GS - Uncomment this line to test transaction rollback
                //throw new Exception();

                //GS - Commit the transaction
                p.CommitTransaction();
            }

            catch (Exception ex)
            {
                p.RollBackTransaction();

                //GS - Set the object Ids to 0 to show 
                //they've not been serialised
                p.Id = 0;
                foreach(Child c in p.Children)
                {
                    c.Id = 0;
                }
            }

            //GS - Prove it was serialised by printing its ID
            Console.WriteLine("Last Id created = " + p.Id.ToString());
            Console.WriteLine("Here are my children..");
            foreach (Child c in p.Children)
            {
                Console.WriteLine(c.Tag + " has id = " + c.Id.ToString());
            }

            //GS - Hold the console window open until the user hits enter
            Console.ReadLine();
        }
    }
}

Review of my Web Client Software Factory Talk

On Wednesday night I gave my WCSF presentation to the North East Scotland .Net User Group. Colin Mackay came along and afterwards wrote the following review on his blog

Now, I have to say that watching someone code for 90 minutes is generally not my idea of fun, but Gary's presentation skills are such that he keeps you entertained during the slow parts (such as when the code was compiling and so on) and his explanations are pitched at just the right level so that you understand what's going on without over explaining anything and ensuring that everyone is keeping up.

Read the rest of the review at Colin's site

Twitter Updates


    Follow me! :-)
    www.flickr.com
    GaryShort's photos More of GaryShort's photos