August 2007 - Posts

Factory Pattern

I was asked a question last night about the factory pattern.
Factories construct and return an instance of a class type. Why you might ask, well first all the creational logic for my classes exist in one place. Secondly no modifications are needed to the factory if a new implementation is created (i.e. the factory is not tied to any specific concrete implementation).

Here is a reference implementation:

    /// <summary>
    /// Base Class for all accounts
    /// </summary>
    public abstract class Account
    {
        /// <summary>
        /// Override of the ToString so we can see what type of account we have
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return String.Format("This is a {0} account", this.GetType().FullName);
        }
    }
   
    /// <summary>
    /// CheckingAccount Implementation
    /// </summary>
    public class CheckingAccount : Account
    {
    }
   
    /// <summary>
    /// SavingsAccount Implementation
    /// </summary>
    public class SavingsAccount : Account
    {
    }   
   
    /// <summary>
    /// AccountFactory
    /// </summary>
    public class AccountFactory
    {
        /// <summary>
        /// Uses Reflection to figure out what type of account the user wants and news one up
        /// </summary>
        /// <param name="accountType">type of account the user wants</param>
        /// <returns>Account object</returns>
        public static Account CreateAccount(string accountType)
        {
            return Activator.CreateInstance(Type.GetType(accountType)) as Account;
        }
    }   

    /// <summary>
    /// Here is how I would use the factory
    /// Note: that the string literals could be comming from the database, a config file, etc
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            Account a = AccountFactory.CreateAccount("FactoryTest.CheckingAccount");
            Console.WriteLine(a);
           
            a = AccountFactory.CreateAccount("FactoryTest.SavingsAccount");
            Console.WriteLine(a);

            Console.ReadKey();
        }
    }
   
  
The beauty of the Factory Pattern is let’s say for example if I add a new type of account 401kAccount. All I have to do is create that class, ensure that it inherits from the base class. Then everywhere in my code that calls the factory will be able to handle the new account type without modification. Using reflection prevents event the need to modify the Factory.   

Resources:
Design Patterns by Christopher G. Lasater Wordware Publishing (c) 2007
http://en.wikipedia.org/wiki/Factory_method_pattern
http://www.dofactory.com/Patterns/Patterns.aspx
http://www.codeguru.com/csharp/.net/net_general/patterns/article.php/c4673/

 

Posted by sweisfeld | with no comments
Filed under: ,

A Gift for Teaching Push for Pencils & Earthquake in Peru

At the last few user group meetings (http://www.onetug.org) we have been collecting schools supplies for needy children in Central Florida. In total we have collected over 1400 items: including 432 crayons, 428 pencils, 228 colored pencils and 210 pens. Thank you to everyone that has contributed!

We also collected $50 in donations for the Earthquake victims in Peru at the meeting last night. The donation has been forwarded to the American Red Cross.

 

Here are PDF's of the Thank you letters ONETUG got from A Gift for Teaching and the Red Cross
http://www.onetug.org/DNN/Portals/0/member_files/AGiftDonation.pdf
http://onetug.net/Documents/2007_11_11_AGiftThankyou.pdf
http://www.onetug.org/DNN/Portals/0/member_files/RedCrossDonation.pdf

Posted by sweisfeld | with no comments

Flatten a Hierarchy in SQL Server 2005

Hierarchies are common in many applications today. Some classic examples are the reporting chain in your company. For example you are an employee and you report to another employee and that employee. A common way to represent this is utilizing an "Adjacency List Model". A good explanation of this can be found in Joe Celko’s book and on this website (http://www.sqlsummit.com/AdjacencyList.htm). The basic idea is that a boss column exists on the employee table a unary relationship. So utilizing the new common table expression (http://msdn2.microsoft.com/en-us/library/ms175972.aspx) in sql server 2005 it is easy to build a hierarchical query. Once the hierarcial query is built on needs to add a column that build the entire tree up. In the example in the sql server books online this is done in the sort field. The only issue we have is that it is difficult to break up the tree into its individual parts since the pipe delimiters are at different places. The easy fix to this is to pad the field so that every name is the same length. Then I can use a simple substring to break the names back apart into individual columns. Poof, a hierarchy is now horizontal in columns! YEA!

USE AdventureWorks;
GO
WITH DirectReports(Name, Title, EmployeeID, EmployeeLevel, Sort)
AS (SELECT CONVERT(varchar(255), c.FirstName + ' ' + c.LastName),
        e.Title,
        e.EmployeeID,
        1,
        CONVERT(varchar(max), CONVERT(char(100), c.LastName + ', ' + c.FirstName) + '|')
    FROM HumanResources.Employee AS e
    JOIN Person.Contact AS c ON e.ContactID = c.ContactID
    WHERE e.ManagerID IS NULL
    UNION ALL
    SELECT CONVERT(varchar(255), c.FirstName + ' ' + c.LastName),
        e.Title,
        e.EmployeeID,
        EmployeeLevel + 1,
  CONVERT(varchar(max), Sort + CONVERT(char(100), c.LastName + ', ' + c.FirstName) + '|')
    FROM HumanResources.Employee as e
    JOIN Person.Contact AS c ON e.ContactID = c.ContactID
    JOIN DirectReports AS d ON e.ManagerID = d.EmployeeID
    )
SELECT
 EmployeeID,
 Name,
 Title,
 EmployeeLevel,
 RTRIM(SUBSTRING(sort, 1, 100)) AS lvl1,
 RTRIM(SUBSTRING(sort, 102, 100)) AS lvl2,
 RTRIM(SUBSTRING(sort, 203, 100)) AS lvl3,
 RTRIM(SUBSTRING(sort, 304, 100)) AS lvl4,
 RTRIM(SUBSTRING(sort, 506, 100)) AS lvl5,
 RTRIM(SUBSTRING(sort, 607, 100)) AS lvl6,
 RTRIM(SUBSTRING(sort, 708, 100)) AS lvl7,
 RTRIM(SUBSTRING(sort, 809, 100)) AS lvl8,
 RTRIM(SUBSTRING(sort, 910, 100)) AS lvl9,
 RTRIM(SUBSTRING(sort, 1011, 100)) AS lvl10
FROM DirectReports
ORDER BY Sort;
GO

 

Posted by sweisfeld | with no comments
Filed under: ,

SPN’s (Service Principal Names)

Having problems authenticating? Maybe you need an SPN?

Here is some information on SPN’s (Service Principal Names), but basically SPN’s allow a client to find a service for Kerberos authentication.

SPN information from MSDN
http://msdn2.microsoft.com/en-us/library/ms677949.aspx

SPN information from TechNet
http://technet2.microsoft.com/windowsserver/en/library/b3a029a1-7ff0-4f6f-87d2-f2e70294a5761033.mspx

SPN information from SQL Server Docs
http://msdn2.microsoft.com/en-us/library/ms191153.aspx

Posted by sweisfeld | with no comments
Filed under: , , ,

Other Orlando UG’s & TSQL Random Raffle Picker

So this has been a busy week for me. Tuesday I went to my first Orlando SQL Server UG meeting (http://www.opass.org) and Wednesday I went to the first Orlando SharePoint UG meeting (http://www.mossmosis.com/schedule_orlando.html). A big thumbs up go to both groups for very successful presentations. So Andy from OPASS did something very interesting at his meeting he challenged all the attendees to figure out a puzzle. Go here (http://www.opass.org/content/showcontent.aspx?contentid=270) to get the full details of the puzzle but basically the task was to build a random raffle picker utilizing TSQL and data from the Adventure Works database in SQL Server 2005. Now while I wasn’t able to get it done at the meeting in the time allotted, being the big geek I am I went home and put together my solution. Now I don’t want to take full credit for this solution I did have some help (hey I am a .NET guy). When I was leaving the meeting I overheard one of the other attendees say “while” and during my ride home from the meeting all kinds of light bulbs went off.

DECLARE @empl int, --holds the employee id of the winner for each round
      @count int -- holds a count of the number of times we need to loop

--holds 1 record for each ticket the person has
CREATE TABLE #tmpB
(
      EmployeeID int
)

--holds the list of winners
CREATE TABLE #tmpC
(
      EmployeeID int
)

--Get all the people and the number of tickets each should have and store in temp table
SELECT EmployeeID, ROUND((VacationHours / 4) + (SickLeaveHours * 2), 0) AS tickets
INTO #tmpA
FROM HumanResources.Employee

--Set the count equal to the number of people that still have tickets on the temp table
SELECT @count = (SELECT COUNT(*) FROM #tmpA WHERE tickets > 0)

--While at least one person still has tickets on the temp table
WHILE (@count > 0)
BEGIN
      --Copy the list of people that still have tickets to table B
      INSERT INTO #tmpB
      SELECT EmployeeID
      FROM #tmpA
      WHERE tickets > 0

      --decrement the number of tickets each person has
      UPDATE #tmpA
      SET tickets = tickets -1
      WHERE tickets > 0

      --update the count to reflect the number of people that still have tickets
      SELECT @count = (SELECT COUNT(*) FROM #tmpA WHERE tickets > 0)
END

--Pick the winners from temp b
--pick 20 winners
SELECT @count = (20)

WHILE (@count > 0)
BEGIN
      --Select a random ticket from the table
      SELECT @empl = (SELECT TOP 1 EmployeeID FROM #tmpB ORDER BY NEWID())
      --decrament the counter so we dont loop forever
      SELECT @count = @count - 1
      --Put the winner on the winners table
      INSERT INTO #tmpC (EmployeeID) VALUES(@empl)
      --Remove all the winners tickets from the table
      DELETE FROM #tmpB WHERE EmployeeID = @empl
END

--Display the winners
SELECT * FROM #tmpC

--Clean up
DROP TABLE #tmpA
DROP TABLE #tmpB
DROP TABLE #tmpC

Posted by sweisfeld | with no comments
Filed under: ,