Monday, 10 December 2007

Dynamic Queries in LINQ

Dynamic queries are usually used in search screens where the search criteria is optional. This illustrates how to create dynamic queries.

Dynamic Queries

The following code creates a dynamic query:
1.MyDataContext context = new MyDataContext();
2.var query = from customer in context.Customers select customer;
3.var filteredQuery = (from customer in query where customer.ID == newCustomerID select customer).ToList();

This is how it works:
1. Create a new context to query
2. Creates the first part of the query
3. Adds further criteria to the original query, paying attention to the bold part in line 3, where we extend the query variable.

Saturday, 1 December 2007

Web Client Software Factory and Dependency Injection

The Web Client Software Factory is a combination of frameworks to give any .NET web app a head start using the Model View Presenter pattern and the Microsoft Enterprise Library for things such as Error handling policies and Logging. In this way you can be assured that you are starting with a bedrock that is fully testable and refactored. It also provides guidance with real-life samples to get you up and running. We have a team that have built a common framework for the Lend Lease .NET development team based on the WCSF, using LINQ as well in VS 2008.

I looked at using this for my last project at Pfizer - but the project didn't give us the luxury of learning and adapting this framework on the job. We now have the support of Lend Lease to develop this framework which is fantastic.

One issue is that the "recipes" that generate the stubs for different modules don't work with 2008 (even though the code compiles). There are hacks to get the WCSF working in 2008 - but we are just having the team leads of the different projects generating these stubs in 2005 for the other developers.

One of the techniques that the Web Client Software Factory relies upon is
dependency injection. A good description of it can be found here:
http://webclientsoftwarefactory.blogspot.com/2007/08/what-is-dependency-injection.html

Monday, 19 November 2007

I've moved from SSW to Oakton!

Just had my last day at SSW after 8.5 years! We had a great time at Strike Bowling @ Fox Studios in Centennial Park - and an even better dinner at Cine Italian restaurant down the street. After the obligatory speeches and hugs, that was it!!!

I started at Oakton this morning with 5 others (the equal largest weekly intake) with a lovely woman called Fiona Begg. I was blown away by her enthusiasm for the company and it has definitely rubbed off on me. I am very much looking forward to starting on a new Lend Lease project through Oakton (Stock Code 'OKN') which will deal with Property Funds Management.

After the induction, I was given a runthrough of the work to be done at Lend Lease. I also had some spare time which I used to look into the Property funds management business in general. I found some very illuminating articles on the software currently available at http://www.avo.gov.au/PropertyFundManagementDiscountedCashFlow.htm. Looking through some of the articles linked to on this site gave me a good overview of some of the tools used. It appears that there is an industry leading application called "DYNA" which is currently used by Lend Lease - along with Excel.

It seems that what ever the company, there is always a worrying number of spreadsheets lurking around where business-critical applications should be. I don't want to go into the many problems there are with spreadsheets - but I would hope that you don't want millions of dollars going awry when you incorrectly cut and paste a formula! After all the spreadsheets I've seen at Queensland Water Infrastructure and Pfizer, my thoughts were .... "Oh no! Not again!"

I also noticed that (like most companies), that Timesheets are not kept at the task level, but rather X number of hours is just allocated to a client. This is a lot simpler than the level of detail we had to provide at SSW. Perhaps our clients were just more demanding.

One of the things that Mark Liu mentioned when I gave him a lift to the bowling was that his brother John Liu (with whom I worked with for a year at SmartSalary) is also at Oakton. This means that I will potentially be working with 4 people I have worked with previously :

  1. Ryan Macnamee will be my supervisor (with whom I worked on the Qantas meal forecasting application at his old company Datacom)
  2. Andrew Weaver (who used to work at SSW) who now works at Lend Lease directly
  3. Tristan Kurniawan (who is contracting to Lend Lease via SSW)
  4. John Liu (if he moves to the Lend Lease project).

So it is really more like changing clients at SSW than moving company... Only bad thing is that I have to start 7:45am tomorrow!

Friday, 16 November 2007

The old schema refresh problem with SQL Server 7.0 still exists in SQL 2005

The metadata in SQL Server 2000 and 2005 databases do not automatically update for views when you add to or remove a column to the underlying table. They will only show the original columns from when the view is updated. For example, if you run the following script, you will only be shown the first 2 columns even though there are now 3 columns in the table:



if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Client]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[Client]
GO


CREATE TABLE [dbo].[Client] (
[ClientID] [int] IDENTITY (1, 1) NOT NULL ,
[Name] [varchar] (50) NULL ,
) ON [PRIMARY]
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[vwClient]') and OBJECTPROPERTY(id, N'IsView') = 1)
drop view [dbo].[vwClient]
GO

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO

CREATE VIEW dbo.vwClient
AS
SELECT dbo.Client.*
FROM dbo.Client


GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
ALTER TABLE dbo.Client ADD
DateUpdated datetime NULL
GO
COMMIT


SELECT * FROM vwClient


Even worse, if you remove a column, you will get runtime errors guaranteed if you don't recreate all dependant views. To fix this, you should perform an sp_refreshview 'viewname' on the views whose underlying tables have been updated - or you can manually trigger this by going to design view of the view, adding a space to the query definition and clicking OK.

The simplest way to do this is for all views is to use the following stored procedure to detect any changes or problems:



if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[procRefreshAllViews]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[procRefreshAllViews]
GO

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS OFF
GO



CREATE PROC dbo.procRefreshAllViews
AS

SET quoted_identifier off

DECLARE @ObjectName varchar (255)
DECLARE @ObjectName_header varchar (255)

DECLARE tnames_cursor CURSOR FOR SELECT name FROM sysobjects
WHERE type = 'V' AND uid = 1 Order By Name
OPEN tnames_cursor
FETCH NEXT FROM tnames_cursor INTO @Objectname
WHILE (@@fetch_status <> -1)
BEGIN
IF (@@fetch_status <> -2)
BEGIN
SELECT @ObjectName_header = 'Refreshing ' + @ObjectName
PRINT @ObjectName_header
EXEC('sp_refreshview ' + @ObjectName)
END
FETCH NEXT FROM tnames_cursor INTO @ObjectName
END
PRINT ' '
SELECT @ObjectName_header = 'ALL VIEWS HAVE BEEN REFRESHED'

PRINT @ObjectName_header
DEALLOCATE tnames_cursor
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO


This problem can be detected easily with SSW SQL Auditor which you can get from http://www.ssw.com.au/ssw/sqlauditor/

The simple way to parse strings to GUIDs in C# or VB.NET

While the religious debate rages between whether we should be using GUIDs as primary keys rages, you can use the Parse method of the System.SqlTypes.SQLGuid class to parse query strings to GUIDs. Here's an example:

return System.Data.SqlTypes.SqlGuid.Parse(Request.QueryString["ParticipantGuid"]).Value;

Thursday, 15 November 2007

Unit Test I created to force the load of Referenced DLLs

One of the issues with .NET applications is that they will load references Just In Time (JIT). I did this code about 2.5 years ago - but it is still useful to force the load of referenced DLLs in case your setup package doesn't deploy DLLs correctly. This code allows you to do a "sanity check" on your application if a user reports bugs when the install your Service/Windows Forms application.



   1:  using System;

   2:  using System.Collections;

   3:  using System.Reflection;

   4:  using NUnit.Framework;

   5:   

   6:  namespace UnitTest

   7:  {

   8:         /// <summary>

   9:         /// Forces load of all assemblies to stop any problems when the Setup Package doesn't have all the correct DLLs 

  10:         ///(we had this specific problem when DLLs were added to SSW.Framework.WindowsUI.WizardForms  FuelAdvance.Components.Windows.Wizards.dll)

  11:         /// (davidklein@ssw.com.au 17/06/2005)

  12:         /// </summary>

  13:         /// 

  14:         [TestFixture()]

  15:         public class DLLDependencyTest

  16:         {

  17:                private static ArrayList m_LoadedDLLs;

  18:   

  19:                public DLLDependencyTest()

  20:                {

  21:                       m_LoadedDLLs = new ArrayList();

  22:                       TestLoadReferencedDLLs();

  23:                }

  24:   

  25:                [Test()]

  26:                public void TestLoadReferencedDLLs()

  27:                {

  28:                       Assembly applicationToTest = AppDomain.CurrentDomain.Load("SSWeXtremeEmails");

  29:                       LoadDLL(applicationToTest);

  30:                }

  31:   

  32:                private static void LoadDLL(Assembly assembly)

  33:                {

  34:                       AssemblyName[] referencedAssemblies = assembly.GetReferencedAssemblies();

  35:                       foreach (AssemblyName referencedAssemblyName in referencedAssemblies)

  36:                       {

  37:                             Assembly currentReferencedAssembly = Assembly.Load(referencedAssemblyName);

  38:                             if (!m_LoadedDLLs.Contains(currentReferencedAssembly.FullName))

  39:                             {

  40:                                    m_LoadedDLLs.Add(currentReferencedAssembly.FullName);

  41:                                    LoadDLL(currentReferencedAssembly);

  42:                             }

  43:                       }

  44:                }

  45:         }

  46:  }

Wednesday, 14 November 2007

What is Project Management Anyway? Different clients have different expectations

The below is a snippet of an email I sent to resolve an issue we had with "Project Management" one of the problems was that our client thought it was one thing (based on their experiences), and we had a different notion of what "Project Management" was.

==========
<Email Snippet>
==========

Marlon,

I think some of our clients such as Westlink and Pfizer have a set idea of what Project Management is – they believe it implies “Dedicated Project Management and Oversight”. We have typically not been providing this as part of our other “Project Management” tasks in many projects, and this could lead to disappointment. In the extremely successful Maximus project, Peter McKeown from Symmetric was doing the project management by:
a. constantly planning
b. suggesting alternative options
c. talking to the clients
d. dictating our work for us
e. giving the project a high level of visibility by organising Friday demos and making sure all stakeholders were present and gave input.

This worked very well. He added real value as a Project Manager.

Project Management

I see project management as separate from creating release plans and the day-to-day meetings that developers have with clients. I don’t believe we are doing project management just by having developers send release plans and sending clarification emails. Project management is not what developers do. Consequently, I have separated this dedicated function out as an optional extra in the SSW Proposal Template. It is like an insurance policy and really needs to be done by a dedicated person that will perform the following function (as per Wikipedia):

"The planning, monitoring and control of all aspects of the project and the motivation of all those involved in it to achieve the project objectives on time and to the specified cost, quality and performance."

“Project management is quite often the province and responsibility of an individual project manager. This individual seldom participates directly in the activities that produce the end result, but rather strives to maintain the progress and productive mutual interaction of various parties in such a way that overall risk of failure is reduced.”

I believe the project manager should take on the role of and liaising with the client about problems and potential problems with the project. It is the project managers role to do the following:

1. Helping to make sure the customer is informed of budget overruns and technical issues and given the earliest possible opportunity to:
a. stop the project
b. remove tasks
c. reassign tasks to cheaper resources (e.g. China).
d. Reassign the tasks to more effective resources

This is assisted by generating Timing, ETAs and financial reports that developers don’t normally generate:
a. Financial Reporting e.g. using Microsoft Project via TFS WorkItems (based on our proposal spreadsheet) to show baseline estimates against actual figures and predict problems and deadlines.
b. Updating TimePRO projects and the project status and sending out the Project Progress report.

2. Keeping a close eye on developers/team leaders to see if there are any problems that have simpler solutions or would be better done by an expert/outside resource or using a 3rd party tool.

3. Helping to make sure that the ongoing quality of the product is good standards are enforced. E.g.
a. Identify opportunities for automated testing and unit tests.
b. Running code auditor/SQL auditor/FXCop.
c. The most effective tools are used such as using code generators for repetitive work.
d. Suggesting refactoring possibilities if there is repetitive code.

4. Helping to Removing any client-side or developer-side bottlenecks to development (e.g. following up questions that the client is not answering/developers just waiting on response or are stuck with a product bug or coding issue)

5. Helping developers to determine what should go into the current release and what should go later (scoping – ie what is in scope/out of scope)

6. Updating the scope documents (this is not done in normal projects; we typically create the document and leave it to gather dust)

2 main tasks are performed by developers which were previously classified as “Project Management” by us are:
1. “Project Administration” which includes creating releases and sending out release plans and done emails & timesheets
2. “Requirements Gathering, Client Meetings and Clarifications”

With this in mind.... I believe that dedicated project management (e.g. what I’ve been doing with Westlink) should be an optional extra in the template. I have updated the template accordingly as follows:

Updates to Template:
1. Changed “Project Management” to “Project Administration” (I think it reflects our activities more accurately for that task). I kept Project Administration (primarily Timesheets and Invoicing) at 2 hours per 40 work hours.

2. Added new task type – “Requirements Gathering, Client Meetings and Clarification.” I put this down as 4 hours per 40 work hours.

3. Added an “Optional Extra Items” Group to clearly indicate that a dedicated Project Manager is not normally used on our projects. Our normal task system (eXtreme Emails) provides basic project management capabilities.
4. Includes the “Weeks” calculation

Figure 1 - Updates to the SSW Proposal Template







Figure 2 - Added Dedicated Project Management as an optional Extra for the whole project


==========
</Email Snippet>
==========

Tuesday, 13 November 2007

Automating Deployment between Development, Test and Production Environments for ASP.NET applications

This is a great way of automating the deployment of the correct settings to your Dev, Test and Production Environments - courtesy of Scott Gu:

Use ASP.NET Web Application Projects (which have MSBuild based project files) Open the VS Configuration Manager and create new "Dev", "QA", "Staging" build configurations for your project and solution Add new "web.config.dev", "web.config.qa", and "web.config.staging" files in your project and customize them to contain the app's mode specific configuration settings Add a new "pre-build event" command to your project file that can automatically copy over the web.config file in your project with the appropriate mode specific version each time you build the project (for example: if your solution was in the "Dev" configuration, it would copy the web.config.dev settings to the main web.config file).Once you follow these steps, you can then just pick the mode your solution is in using the configuration drop-down in the VS standard toolbar

For more, see:
http://weblogs.asp.net/scottgu/archive/2007/09/21/tip-trick-automating-dev-qa-staging-and-production-web-config-settings-with-vs-2005.aspx