.Net ramblings
# Sunday, 15 July 2007
Migrating from Windows software RAID to Hardware RAID
i started a thread on the DELL community forums asking about migrating my windows 2003 software RAID setup to a hardware RAID controller, without reinstalling windows.  you can read the thread to get the context for these documented instructions below:

success. after a marathon 7 hour session in the datacenter it finally works. however the whole thing was much too stressful for my liking!

my problems were significantly compounded by the lack of a CD drive, so i had to get my imaging software (Terabyte Unlimited 'Image') to boot via a USB drive, which was never going to be easy with a Dell BIOS etc. although to be fair it does work, once you understand that you must reboot after configuring the BIOS to recognise the USB drive, and then go into the bios again and tell it what order to boot in.

i thought it useful to document the steps i took in case anyone else is in a similar situation.

in summary, i wanted to do an in-place migration from software raid in windows 2003 to hardware raid with the dell/adaptec CERC 6 channel SATA RAID card. all without using a CD drive (trust me, get one if you ever have to do this. i tried but couldn't get the BIOS to recognise the drive).

i got a very helpful email from Terabyte support before starting the migration:
****************************************
Hello,
If you just have a single simple volume (once the software RAID is broke), you can remove the dynamic drive by changing the file system ID back to 7 (via BootItNG partition work/properties). If you backup while dynamic, it will just backup the whole dynamic partition sector by sector.
So what I'd personally do is:
1. break the raid, (maybe remove the secondary drive as a backup)
2. ensure it's a single simple volume that's left (I'm assuming you just have c,
3. boot BootItNG, change the file system ID to 7,
4. boot back to windows (if it didn't boot, just put back the file system id to dynamic),
5. install the CERC drivers (if needed),
6. do the image, with byte-for-byte validation (slower in windows because it thrashes a bit),
7. ensure I can access the image to restore with Image For Dos or Image For Linux.
8. Configure the hardware RAID,
9. restore the image (use additional option of TA when restoring the boot partition).
*****************************************

windows software RAID requires dynamic disks, which are not officially reversible back to basic disks. this further complicated the process because i wanted to go back to basic disks for the RAID. you can convert back to a basic disk as described above with BootItNG, and also via the DskProbe windows support tool, instructions available from: http://www.nthelp.com/NT6/dynamic.htm. although i also read that if you use software raid, you shouldn't use this approach, so i unplugged the second drive, booted into windows and removed the mirror, and the offline disk from Windows Disk Manager. Then i changed to a basic disk via DskProbe and it did work, although DiskManager reported a single drive, which was marked offline or something very worrying like that. however the files were all there and working etc.

i followed the instructions above, although i did install the RAID card before changing any drivers or removing the software RAID, and i got windows to load up the drivers for it, so it would work automatically once booting from the RAID controller. this was one less problem in the equation and i was keen to get it out of the way as early in the process as possible.

to get Image For Dos to boot off USB, i used the bundled 'makedisk' utility without any init strings. I configured the BIOS to emulate a USB drive as a hard drive, floppy did not work. Then rebooted and changed the boot sequence so that the USB drive came first.
the disk image (of the 'active' drive, the other was still unplugged) took about 30 minutes with byte-for-byte validation, ~25Gb of data, copying to an external USB drive, using ImageForDos. i had to change the keyboard to a PS2 connection because in my first attempt the program locked out the keyboard after identifying the USB drive.

then i verified that i could access the image with the restore option. and went ahead with setting up a RAID mirror in the CERC configuration utility. plugged in both drives into ports 4 and 5. incidentally i needed a longer SATA cable for drive0 because it only had a 4inch cable and the RAID plugs on the card are miles away from the drive bays. The cable for the other drive fit with a stretch into the last port on the card.
so i did a reboot, pressed Ctrl-A etc. initialise the 2 drives. set up a RAID 1 mirror as per the manual instructions. i used the quick-init option because i was really in a hurry to get the job done. i set high priority also. i did not 'clear' the drives, but this may have been no harm to do.

then i rebooted and loaded my restore image with ImageForDos. the 'TA' option referred to in the instructions marks the partition active and inserts a standard MBR. it took about 30 minutes again and finished successfully. i was a bit worried because the restore program asked me which drive did i want to restore to, i assumed it didn't matter and chose the second drive. my cause for concern was that i wasn't sure if the controller would do it's mirroring thing during this restore operation. my fears were doubled when i rebooted after the restore, and got a message something like "no operating system, F1 to continue, F2 to setup". at this stage i had about 5 minutes before 'visiting hours' were over in the datacentre and i would have had to take the server home for the weekend to get it ready before monday 9am, no thanks! i thought it had failed. i was about to pack up and go home when i went in to look in the bios one last time in case i missed anything. i didn't change anything, and i also inspected the RAID config via the BIOS utility, but again, didn't change anything. i tried to turn off caching as a desperate attempt to fix the boot problems, but it wouldn't accept the change for some reason. anyhow, i rebooted again, said a quiet prayer, and i couldn't believe it but windows started loading, i was never so happy to see that Windows logo appear on screen (you probably had to be there to understand, 7 hours of white noise from being surrounded by a gzillian racks, no lunch, very frustrated etc!)

now all is well with the 2 drives showing up 'optimal' in the DELL/Adaptec storage manager. i gather this means that the build/verify has already completed in the background. the URL for the storage manager is http://tinyurl.com/2nddta

i didn't want to install all that dell 'management' software that came with the RAID card.
another good thing i forgot to mention. windows disk manager now shows a healthy primary partition for C:. it doesn't say 'fault tolerant' anymore obviously because the software raid is gone and the hardware RAID is abstracted away from the windows disk manager.

hope this helps someone someday.


Sunday, 15 July 2007 00:33:07 (GMT Daylight Time, UTC+01:00)  #    Comments [3]  General | Windows Server

# Thursday, 05 July 2007
HowTo: Invert datagrid rows and columns
this is a bit of a strange one.  I have a table and it has approx 60 columns, with only one row being shown.  I wanted a human-readable display of all the fields in the table for any given row, i.e. i didn't want the user to have to scroll several screens across just to read the data for a single row.  Vertical scrolling is obviously easier, so i wrote a Repeater implementation, which works nicely.  For a table with X columns and Y rows, the output will have X rows and Y columns.  Screenshot below shows the output of all the ServerVariables in a HTTP-request, which is a good example of a datasource that does not naturally fit the traditional 'grid' display.
<!-- ASPX usage -->
<xyz:VerticalGrid ID="vGrid" runat="server" />

// sample databinding...
this.vGrid1.DataSource = new DataView(dataSet1.Tables[0]);
this.vGrid1.DataBind();

/// <summary>
/// A Repeater control that shows the rows and columns inverted.
/// No template is required for the items.
/// The datasource must be an ADO.Net DataView
/// </summary>
[ToolboxData("<{0}:VerticalGrid runat=server></{0}:VerticalGrid>")]
public class VerticalGrid : Repeater
{
public VerticalGrid()
{
this.EnableViewState = false;
}

protected override void Render(HtmlTextWriter writer)
{
// invert the rows and cols
if (!(base.DataSource is DataView))
throw new Exception("Error: only a dataview datasource can be used");

DataView dv = base.DataSource as DataView;

// output start of table
writer.Write("\n<table class='grid'>");

// output each row
for (int i = 0; i < dv.Table.Columns.Count; i++)
{
writer.Write("\n<tr class='{0}'><th>{1}</th>", i % 2 == 1 ? "gI" : "gA", dv.Table.Columns[i].ColumnName); // output the column name in the first cell. class names gI and gA are abbreviations of gridItem gridAlternatingItem, to reduce output markup.
for (int j = 0; j < dv.Count; j++)
writer.Write("<td>{0}</td>", dv[j].Row.IsNull(i) ? "&nbsp;" : dv[j][i].ToString());
writer.Write("</tr>");
}
writer.Write("\n</table>");
}
}




Thursday, 05 July 2007 15:53:40 (GMT Daylight Time, UTC+01:00)  #    Comments [0]  Asp.Net

Vista Driver problems, Formac USB Hard Drive
i just got a 160Gb Formac portable USB/firewire hard drive. I plugged it in to Vista and i get a message saying that Windows needs to install a driver to get it to work, i wasn't expecting this as i thought these drives did not need any drivers.  I let it check Windows Update but it found nothing.  I tried the firewire option but it was no different.  I contacted Formac tech support and got the following reply, which was actually very helpful:
"If a driver is required, then it is required for your USB, or FireWire interface inside your PC. External harddrives didnĀ“t require special drivers, because they are ATAPI compatible."
I grabbed an old USB card reader which i know does not require any additional drivers, and i plugged it in.  I got 12 prompts to install drivers and each time it searched Windows Update and found nothing.  I took a guess at searching in c:\windows and it found them one by one.  I couldn't figure out why Windows would not search its own driver store automatically.  Apparently there is some bug with Vista where you can get a corrupt driver cache file and if you delete it then it will solve all these problems. 
The culprit file is called INFCACHE.1 and it's located in c:\windows\inf.  I discovered this on a newsgroup post.  This is the relevant part:

The solution to this annoying problem (I had it on one PC), seems to be to locate and delete the file INFCACHE.1, which may be corrupted and causing the problem. To delete this file, you will first have to modify its permissions so the users group can access it (right-click on the
file->Properties->Security). INFCACHE.1 file.  It's located at C:\Windows\inf (scroll down to the file). (Note: to see INFCACHE.1, you must set Windows Explorer to display hidden and system files)

When modify these system files, i usually find i have to take ownership first for my own user account, then add myself to the permissions with full control.  then you can delete it, or rename it to X_INFCACHE.1, etc.

I'm glad to say Vista is loading all my USB devices nicely now and the Formac drive works beautifully with USB and Firewire.


Thursday, 05 July 2007 10:18:30 (GMT Daylight Time, UTC+01:00)  #    Comments [32]  General

# Tuesday, 26 June 2007
Mounting ISO images in Vista
Just in case anyone was as stuck as i was today trying to virtually load an ISO image.  the Virtual CD Control Panel thing doesn't work in Vista, and for some reason VirtualCloneDrive wouldn't work for me either.
i eventually found a free tool called PowerISO which works great.  you can create several virtual drives and mount an ISO in each one.  i'm currently installing Orcas Beta 1 from an ISO mounted across the network, i wasn't sure if it could do that but it had no problems.


Tuesday, 26 June 2007 16:48:13 (GMT Daylight Time, UTC+01:00)  #    Comments [0]  .Net General | General

# Thursday, 24 May 2007
Upgrading May CTP Web Site projects to Orcas Beta 1 Web Application Projects
This has involved lots of hand-coding in my experience, and i've done a bit of work to automate the process. 

SQL Metal Stored Procedure Names

Firstly i found that SqlMetal no longer removes the underscore characters with Orcas Beta 1, which typically leaves hundreds of compile errors that are time consuming to fix by hand.  Visual Studio can replace these using regular expressions with a little preparation, depending on your naming conventions.  All my stored procedures are of the form TableName_SELECT_Xyz, or TableName_UPDATE_Xyz etc.  I found i could fix all the compile errors by scanning for {[a-zA-Z]}SELECT and replacing with \1_SELECT to cover the left hand side underscore, and similarly you can do the reverse to insert a right hand side underscore if there is an a-z character immediately after the SELECT (if there are brackets or punctuation then you probably don't want to insert an underscore).  I ran this for SELECT INSERT UPDATE and DELETE, 2 times each.  takes a minute but saved me a lot of time.
More info on using regular expressions within Visual Studio.

Adding Namespaces when upgrading from a 'web site' project.

The Orcas 'convert to web application' facility is very good i must say.  it actually works.  no more half baked designer.cs files or unsynchronised control members in code behind etc.  But it doesn't add namespaces to your aspx or code-behind files, which is a real pain if you have 50+ aspx pages in your site, and several projects to convert.  I wrote a simple winform app to attempt to relieve the hand-coding required.  it also takes out a few of the retired namespaces from MayCTP and adds in the Beta 1 / Linq replacements.  You can customise the namespaces to add/remove, and specify the new namespace to add to the web site aspx + code behind files.  it comes with no warranty and may screw up your files so always take a backup before running!
the idea is that you run the tool on your web site project directory, then create a blank WAP project in Orcas and copy in the files.  Then run the Orcas 'convert to WAP' command on the project root.  if it is successful you will see each aspx page expanded in the project tree.  some pages don't convert because of compile errors with custom controls etc.   i usually found it took a bit of working through the compile errors first before some of the pages would successfully convert to the WAP format.  here's a screenshot and the code if anyone wants to run it:



Source code + executable (zip 36 Kb)
Thursday, 24 May 2007 17:36:00 (GMT Daylight Time, UTC+01:00)  #    Comments [2]  

# Thursday, 17 May 2007
Deploying Crystal Reports for Orcas Beta 1

I know we're not supposed to be going live with .Net 3.5 / Orcas Beta 1 yet, but hey. 

I ran into a Crystal Reports deployment problem with an asp.net web application developed in Orcas beta 1, using the bundled version of crystal reports.  The problem is that the crystal report dlls used in a Beta 1 project are 10.5.3700.0 but there don't appear to be any merge modules available to support this version number, so there is no supported way to run the Orcas version of Crystal Reports on a server, without installing Orcas itself.  I tried numerous options of digging out the 10.5.3700.0 dlls from program files\common files\business objects etc and putting them in the web site bin directory on the server, but that didn't work.  The obvious error message that comes up is as follows:

Could not load file or assembly 'CrystalDecisions.CrystalReports.Engine, 
Version=10.5.3700.0, Culture=neutral, PublicKeyToken=692fbea5521e1304' or one of its dependencies.
The system cannot find the file specified.

what i ended up doing was instructing the web application to bind to the 10.2.3600.0 versions of the assemblies, which are already deployed using the normal CR server install.

here is what i added to the end of my web.config file to get it going:

     ....
<runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="CrystalDecisions.CrystalReports.Engine" publicKeyToken="692fbea5521e1304"/>
                <bindingRedirect oldVersion="10.5.3700.0" newVersion="10.2.3600.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="CrystalDecisions.CrystalReports.Shared" publicKeyToken="692fbea5521e1304"/>
                <bindingRedirect oldVersion="10.5.3700.0" newVersion="10.2.3600.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="CrystalDecisions.Shared" publicKeyToken="692fbea5521e1304"/>
                <bindingRedirect oldVersion="10.5.3700.0" newVersion="10.2.3600.0"/>
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
</configuration>

Thursday, 17 May 2007 17:36:06 (GMT Daylight Time, UTC+01:00)  #    Comments [1]  .Net General | Asp.Net

# Wednesday, 16 May 2007
Sql Triggers for Dummies
i always found the syntax of SQL triggers very difficult to remember, so i'm just posting a sample one here.  it performs a cascade delete on a table that doesn't have referential integrity (because there are 2 potential foreign keys).
ALTER TRIGGER [dbo].[Table1CascadeDeleteTable2]
ON [dbo].[Table1]
FOR DELETE
AS
BEGIN
declare @Ref int;
SELECT @Ref = Ref FROM Deleted;
delete from Table2 where Ref = @Ref;
END


Wednesday, 16 May 2007 18:36:37 (GMT Daylight Time, UTC+01:00)  #    Comments [0]  Database

# Wednesday, 02 May 2007
Crystal Reports: Incorrect Log on Parameters for Dataset source
i spent hours trying to troubleshoot this.  obviously the error makes no sense because CR should not be logging on to anything in a dataset scenario.
anyway, a thousand thanks to Jason for his post on the MSDN forums with the simple answer: set the datasource to the DataTable, not the DataSet.

i can't wait to lose Crystal reports altogether and move to the microsoft reporting thingy, i haven't had time to play about with it yet but at least it will be properly programmed and it won't contain the 10 years of bugs that crystal reports have carried through each release of their software.  </RANT>


Wednesday, 02 May 2007 18:43:46 (GMT Daylight Time, UTC+01:00)  #    Comments [0]  .Net General | Asp.Net

# Tuesday, 01 May 2007
SQL: format numeric to x decimal places
i found this was very hard to figure out.  i read lots of approaches to hack the data into char(5) etc to give you "23.54" using Round() etc.  but that seemed messy.  the key is to cast to type Numeric(size, decimalPlaces).  for example:
CONVERT(Numeric(10,2), (Count(ID) * 100. / @Total)) as Percentage

the above will display "23.54" (for example), including rounding, as a number.


Tuesday, 01 May 2007 12:53:15 (GMT Daylight Time, UTC+01:00)  #    Comments [3]  Database

# Monday, 30 April 2007
LINQ: upgrading May CTP projects to Orcas Beta 1
here are a few of my main findings/hurdles encountered when upgrading May CTP web projects to Orcas beta 1 Web Application Projects.  I'm targeting version 3.5 of the framework for deployment on a Server 2003 with .Net 2.0 runtime installed, i will update this article if it doesn't work out. 
  • if you had any code in the "App_Code" folder, VS will probably have set the compile action to "content", it should be changed to "compile".  otherwise you will get errors like: The type or namespace name 'xyz' could not be found (are you missing a using directive or an assembly reference?)
  • you'll have to remove any reference to the System.Query and System.Expressions, these are not part of the new LINQ spec.
  • Replace System.Data.DLinq with System.Data.Linq.
  • if you want to use any LINQ expressions, like "from x in db.Table select x" then you need to include the System.Linq namespace.  otherwise you will get errors like 'System.Data.Linq.Table<xyz>' does not contain a definition for 'Where' and no extension method 'Where' accepting a first argument of type 'System.Data.Linq.Table<xyz>' could be found (are you missing a using directive or an assembly reference?)
  • you will also need to include System.Linq.Expressions if you are using "language-level code expressions to be represented as objects in the form of expression trees".
The old LINQ assemblies are versioned 1.0.2319.19044 (May CTP) but the new ones for Beta 1 are versioned 2.0.0.0.  Have a check through the referenced assemblies in your project to make sure you have the latest versions. 

Crystal reports

look out for the new crystal report assemblies, 10.5.3700.0.  a web app referencing the new versions in web.config will complain if these versions are not available on the server.  i'll update soon when i have found out how to do this.


Monday, 30 April 2007 11:50:28 (GMT Daylight Time, UTC+01:00)  #    Comments [0]  .Net General | Asp.Net