Error trying to install or run vsi file

If you are trying to run a .vsi file and have both VS 2005 and VS 2008 you may encounter an error that indicated the file microsoft.wizardframework could not be loaded:

could not load file or assembly 'microsoft.wizardframework

Below are the steps I followed to correct:

  1. Check the GAC (C:\WINDOWS\assembly) for the assembly Microsoft.WizardFramework.dll
  2. If it does not exist, check that it exists in C:\Program Files\Micro
    soft Visual Studio 9.0\Common7\IDE\
  3. If it does, then open a VS command prompt and add the dll to the GAC
    gacutil /i "C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\Microsoft.WizardFramework.dll"
  4. Check for the dll in C:\WINDOWS\assembly
  5. You should now be able to run the VSI

Unit Testing and Integration Testing with your database

I like to do a combination of unit and integration testing with my projects.  When testing code that update the database you need to account for the state of your databse.  If you want repeatable tests, you either need to use stubs or mocks or find a way to return your databse to the state it was in prior to your tests running.

 One approach that I have been using with success is leveraging the System.Transaction name space within my tests that update the database.  Below is some sample code using the NUnit testing framework.  By wrapping the code that updates the database within a transaction (using (...)) the save operation is rolled back:

 /// <summary>
/// Transaction is not "completed" so gets rolled back preventing
/// test data from being persisted to db.
/// </summary>
[Test]
public void Should_Insert_A_New_Info_Object_Into_DB()
{
using (TransactionScope transScope = new TransactionScope())
{
string testDateTime = DateTime.Now.ToString();
Info info = AddTestRecord(testDateTime);
Assert.IsTrue(info.Subject == "Subject: " + testDateTime);
info.Save();
Assert.IsTrue(info.Subject == "Subject: " + testDateTime);

}

}

Hope people find this technique useful.

VS 2008 RTM Error

If you receive the below error when trying to build a project that was composed using the VS 2008 Beta, you need to modify your config files.

 Change the assembly version from 2.0.0.0 to

Version=3.5.0.0

Error 1 Could not load file or assembly 'System.Data.DataSetExtensions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of its dependencies. The system cannot find the file specified.

Database Paging and Sorting with CSLA Part 3 - The presentation layer

This is the final part on how to implement database paging with a custom CSLA business class and SQL Server 2005.  In this post I will demonstrate how to call the business object from part two from the applications presentation layer.  This approach will place minimal code in the presentation layer and allows for clean seperation and the ability to write automated tests against the intended behavior.

 I used a DataGrid and CSLADataSource to present the data from the list class:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataSourceID="CslaDataSourceInfoList"

DataKeyNames="Id" OnRowDeleted="GridView1_RowDeleted" Width="100%" PageSize="10"

AllowPaging="True" AllowSorting="true" EmptyDataText="No Records Available."

PagerSettings-Mode="NumericFirstLast ">

<Columns>

<asp:BoundField DataField="Id" HeaderText="Id" ReadOnly="True" SortExpression="Id"

Visible="False" />

<asp:HyperLinkField HeaderText="Subject" SortExpression="Subject" DataNavigateUrlFormatString="InfoEdit.aspx?id={0}"

DataNavigateUrlFields="Id" DataTextField="Subject" ItemStyle-Width="300" />

<asp:BoundField DataField="CategoryName" HeaderText="Category" ReadOnly="True"

SortExpression="CategoryName" ItemStyle-Width="75"/>

<asp:BoundField DataField="Description" HeaderText="Description" ReadOnly="True"

SortExpression="Description" ItemStyle-Width="200"/>

<asp:TemplateField ControlStyle-Width="50px" HeaderStyle-Width="60px" ItemStyle-HorizontalAlign="Center">

<ItemTemplate>

<asp:Button ID="btnDelete" CommandName="Delete" runat="server" Text="Delete"

OnClientClick="showConfirm(this); return false;" />

</ItemTemplate>

</asp:TemplateField>

</Columns>

</asp:GridView>

<csla:CslaDataSource ID="CslaDataSourceInfoList" runat="server" TypeAssemblyName=""

TypeName="InfoTracker.InfoListItem, InfoTracker" TypeSupportsPaging="True" TypeSupportsSorting="False"

OnSelectObject="CslaDataSourceInfoList_SelectObject" OnDeleteObject="CslaDataSourceInfoList_DeleteObject">

</csla:CslaDataSource>

In the code behind, I used the SelectObject event handler to retrieve the business object and specify the paging information.  Finally in the GetInfoList method I call into the business class to get the data:

protected void CslaDataSourceInfoList_SelectObject(object sender, Csla.Web.SelectObjectArgs e)

{

InfoList infoList = GetInfoList(GridView1.PageIndex, GridView1.PageSize, GetSort(GridView1.SortExpression, GridView1.SortDirection.ToString()),tbSearch.Text);

lblTotalRecords.Text = infoList.TotalRecordCount.ToString();

e.BusinessObject = infoList;

}

private InfoTracker.InfoList GetInfoList(int index, int pageSize, string sort, string searchString)

{

return InfoTracker.InfoList.GetInfoList(index, pageSize, sort, searchString);

}

Database Paging and Sorting with CSLA Part 2 - The CSLA Class

Once your stored procedure is set up (see part 1) you can turn your attention to your CSLA class.   The class I am focusing on here is a read only list called "InfoList" that has a child class "InfoListItem".  This is a design taken directly from Rocky's book and sample application.  The class is declared as follows:

 public class InfoList : ReadOnlyListBase<InfoList, InfoListItem>, Csla.Core.IReportTotalRowCount

 In order to set up the grid view paging I am implementing the IReportTotalRowCount which is needed to get the total records satisfying your sp query.  The following is the implementation for the interface:

#region IReportTotalRowCount Members private int _totalRowCount;

/// <summary>

/// TotalRowCount - this property returns the total row count for the initial list that passed to the

/// constructor.

/// </summary>

int Csla.Core.IReportTotalRowCount.TotalRowCount

{

get { return _totalRowCount; }

}

//Property that can be used in UI to display total number of records
public int TotalRecordCount
{
get { return _totalRowCount; }
}

 #endregion

 Next is the code for the data access.  I have created a FilteredCriteria class that will handle the fields necessary to filter the resuts for paging:

[Serializable]

private class FilteredCriteria

{

internal const int MAXROWS = int.MaxValue;

internal const string DEFAULTSORT = "Subject";

private int _pageIndex;

private int _pageSize;

private string _sort;

private string _searchString;

public string searchString

{

get { return _searchString; }

}

public string Sort

{

get { return _sort; }

}

public int PageIndex

{

get { return _pageIndex; }

}

public int PageSize

{

get { return _pageSize; }

}

 

public FilteredCriteria(int index, int pageSize, string sort, string searchString)

{

//this._pageIndex = GetPageIndex(index,numberOfRecords);

this._pageIndex = index;

this._pageSize = pageSize;

if (String.IsNullOrEmpty(sort))

{

this._sort = DEFAULTSORT;

}

else

{

this._sort = sort;

}

this._searchString = searchString;

}

}

Finally, the Fetch method is coded to pass in the values from the criteria class. This is just a standard sp call, the only additional code is that to get the total row count from the stored procedure and set the _totalRowCount field:

/Get total number of records for GridView paging

dr.NextResult();

dr.Read();

_totalRowCount = dr.GetInt32("TotalRowCount");

That completes the code required for the business class.  The final part is setting up the UI to leverage the pagin logic.  I will demonstrate this in Part 3.

Database Paging and Sorting with CSLA Part 1 - The Database

Part 1 - The Database

I will be writing a multi-part article on how I implemented databse paging and sorting with CSLA business objects for an ASP.NET application.  As a disclaimer, I am sure there are other and potentially better solutions, but I wanted to offer up my solution in hope that it will help others. 

The Problem - When dealing with large amounts of data, it is inefficient to retrieve thounsands of records from a database only to display 10 - 20 records on your UI.  The default paging within a DataGrid does just this.  In addition, each time a user "sorts" a column on a datagrid, all of the records are again being retrieved from the databse.  An alternative to the approach I am using is to use caching within your application to address these issues.

The Solution - I will create a small ASP.NET application, similar to the Project Tracker solution provided with the CSLA.NET framework.  The application I am building is meant to hold "Information", anything from Birthdates to interesting websites, and allows the user to search, sort, add, update, and remove "Information" items.  The homepage will contain a GridView that displays all of the information items contained within the database.  My solution uses a SQL Server 2005 database.  In order to create a layered, Object Oreinted application that is performant, I am using CSLA.Net business objects with Database paging and sorting.

The Database - I am using SQL Server 2005 as my database.  SQL 2005 provides a new function ROW_NUMBER() that along with CTE's provides an easy and performant way to select a subset of data for paging.  The below stored procedure will be called from my application which will pass all of the necessary parameters.  Note that this procedure uses dynamic sql.  You should only use dynamic sql if you fully understand SQL Injection attacks and how to protect your code from them.  In addition, SQL Server will not cache the query execution plan for dynamic sql, so there is a performance trade off.  In this case, being able to limit the nunber of records returned to the middle tier will be worthwhile once your table becomes large with many records.  Also, using EXEC sp_executesql will allow the query plan to be cached, but in my case, since I am also sorting, I would not be able to paramaterize the order by using sp_executesql. 

What is next...
In my next article I will explain what needs to be done within your CSLA business objects to call this stored procedure.  My final article will expain how to hook this functionality up to a GridView in an ASP.Net page.

CREATE PROCEDURE [dbo].[GetInfoList]

(

@PageIndex int,

@NumberOfRecords int,

@Sort varchar(200)

)

AS

BEGIN

SET NOCOUNT ON;

DECLARE @Sql varchar(5000);

SELECT @Sql = ' SELECT InfoList.InfoId, InfoList.Subject, InfoList.CategoryName,

InfoList.Description, InfoList.LastModified FROM

(

SELECT i.InfoId, i.Subject, c.CategoryName,

SUBSTRING(i.Description,0,30) Description, i.LastModified,

ROW_NUMBER() OVER (ORDER BY '
+ @Sort + ') AS RowNum

FROM dbo.Info i

JOIN dbo.Category c on c.CategoryId = i.CategoryId ) InfoList '

 

SELECT @Sql = @Sql + ' WHERE InfoList.RowNum BETWEEN

( ' + CAST(@PageIndex AS varchar(10)) + ' * ' + CAST(@NumberOfRecords AS varchar(10)) + ' + 1 ) AND (( '

+ CAST(@PageIndex AS varchar(10)) + ' + 1 ) * ' + CAST(@NumberOfRecords AS varchar(10)) + ' ) '

SELECT @Sql = @Sql + ' ORDER BY ' + @Sort;

EXECUTE(@Sql);

--Return total number of records for paging

SELECT COUNT(*) TotalRowCount FROM dbo.Info;

END