Wednesday, 26 September 2007

Passing lists to SQL server stored procedures

One much needed feature missing from SQL Server 2005 is the ability to pass "a list of values" from .Net as a parameter to a T-SQL based stored procedure. Loads of scenarios spring to mind but here's a couple of obvious ones: 

  • INSERT a list of values into the database in one "chunky" call (e.g. some IDs from a CheckBoxList)
  • SELECT rows where IDs are IN (<list of IDs>)

You get the idea. Taking the INSERT as an example, there are various approaches you can adopt to achieve the desired result:

  • Use dynamic SQL! I'm not even going to talk about this as this blog entry is on stored procs and dynamic SQL is rarely the ideal solution for obvious reasons ;-)
  • Make a stored proc call for each ID to insert. This is the most common approach I see in various projects, mainly because it is the easiest to implement. The drawback of course is if I were to insert 60 values, it would result in 60 "chatty" calls to the database. Ummm... me hates chatty repetitive db calls plz.
  • Pass comma separated values via a VARCHAR (or similar) parameter. This works fine but has messy "string splitting" in the stored procedure to extract the IDs and then build the SQL statement in the procedure itself. Prone to SQL injection and not the best performance.
  • Pass the list as an XML parameter. This is nicer and is my preferred option (see below)

There are other approaches too (see a detailed description of arrays and lists in sql server by Erland Sommarskog).

Using XML

Using XML for "list passing" has a number of benefits, in particular the ability to pass lists of more "complex types" rather than just single values.  Here's a stored procedure I'm using in a current project (I've stripped out irrelevant code) which takes Study data and inserts it in "one set based query".

CREATE PROCEDURE [dbo].[Study_SaveData](
    @subjectStudyID int,
    @entryAB char(1),
    @studyDataXML XML
    )
AS
BEGIN
    INSERT INTO StudyData (subjectStudyID, entryAB, studyParID, tpID, dataValue)
    SELECT    @subjectStudyID AS SubjectStudyID,
            @entryAB AS EntryAB,
            StudyTab.StudyCol.value('StudyParID[1]','int') AS StudyParID,
            StudyTab.StudyCol.value('TPID[1]','int') AS TPID,
            StudyTab.StudyCol.value('DataValue[1]','float') AS DataValue
    FROM @studyDataXML.nodes('//StudyDataList/StudyData') AS StudyTab(StudyCol)
END

To call this in T-SQL, you would have something like this:

EXEC    [dbo].[Study_SaveData]
        @subjectStudyID = 34,
        @entryAB = 'A',
        @studyDataXML = '<StudyDataList><StudyData><StudyParID>931</StudyParID><TPID>2732</TPID><DataValue>1</DataValue></StudyData>
<StudyData><StudyParID>931</StudyParID><TPID>2733</TPID><DataValue>2</DataValue></StudyData>
<StudyData><StudyParID>931</StudyParID><TPID>2734</TPID><DataValue>3</DataValue></StudyData>
</StudyDataList>'

In your application's DAL layer, your C# calling code could be (again code simplified for brevity):

public static void SaveData(StudyData studyData)
 {
     DBHelper DBH = new DBHelper();
     DBH.AddParameter("@subjectStudyID", studyData.SubjectStudyID);
     DBH.AddParameter("@entryAB", studyData.EntryAB);
     // pass all data values in one go to avoid 'orrible chatty round trips ;-)
     DBH.AddParameter("@studyDataXML", GetStudyDataXMLString(studyData));
     DBH.ExecuteNonQuery("Study_SaveData", CommandType.StoredProcedure);
 }

which calls the method below to translate the DataValueList property (utilising generics) into an XML string:

 private static string GetStudyDataXMLString(StudyData studyData)
 {
     StringBuilder XMLString = new StringBuilder();
     XMLString.AppendFormat("<StudyDataList>");
     foreach (KeyValuePair<StudyData.StudyDataKey, double?> SDKV in studyData.DataValueList)
     {
         XMLString.AppendFormat("<StudyData>");
         XMLString.AppendFormat("<StudyParID>{0}</StudyParID>", SDKV.Key.StudyParID);
         XMLString.AppendFormat("<TPID>{0}</TPID>", SDKV.Key.TpID);
         XMLString.AppendFormat("<DataValue>{0}</DataValue>", SDKV.Value);
         XMLString.AppendFormat("</StudyData>");
     }
     XMLString.AppendFormat("</StudyDataList>");
     return XMLString.ToString();
 }

You get the idea. studyData.DataValueList contains the "list data" to be passed in and inserted into the database. I used StringBuilder for the xml concatenation as in this case I think it fits the bill but purists might prefer an XmlTextWriter approach.

This will ding dang do then! I don't think the code needs detailed explanation, but comments and queries welcome.

In summary, it performs very well and is adaptable for various lists of objects and more complex structures.

Clarkey

Useful Refs

Wednesday, 19 September 2007

IE Developer Toolbar released

I've talked about the IE developer toolbar before, but at that time it was beta.

MS have now (I say now, it was actually in May but hey I had a baby recently so forgive the delay) released an official version for download so you can feel confident in installing it on your work PC (yeh right). Looks very much like beta 3 to me but apparently there are various bug fixes and it is 'more reliable'. Also Vista compatible.

Download it here: http://www.microsoft.com/downloads/details.aspx?FamilyId=E59C3964-672D-4511-BB3E-2D5E1DB91038&displaylang=en

For me, the top features are:

  • browser resize to fixed resolutions (without bookmarklets)
  • html, css validation
  • dom tree views
  • see CSS styles 'firing" on elements
  • View partial/element source
  • easily kill cookies/session, cache
  • color picker

Worth a look.

Here's a good overview (albeit of beta 3) on MSDN if you've not seen it before.

Thursday, 16 August 2007

N-Tier development revisited

Discussion forums on the web are full of .Net N-tier questions, especially on approaches for achieving loosely coupled layers and lightweight data passing mechanisms. Is it ok to pass a DataSet or DataTable? Should I use Custom classes? This article by Imar Spaanjaars is one of the better ones I have seen on the topic:

http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=416

He describes the pros/cons of the different approaches. He is a fan of pulling the "data only bit" out of your business layer objects and putting them into separate "business objects" (only containing data). This aids passing of data between tiers and project referencing.

Question though - does pulling the data out of your business layer objects go against pure OO principles? "An object should consist of the data and operations allowed on that data" etc. Abstract data types (ADTs), encapsulation etc bla bla...

Also, I don't like the BO (business object) terminology as it is used, as this implies more than just data... I'd prefer something like CustomerBDO (business data object) or even CustomerEntity. You could then perhaps lose the "*Manager" suffix notation he has adopted for the business logic layer.

Regardless of these points though, I think custom classes are the correct way forward for "passing data", and datatables etc should be saved for when the types of the results are dynamic, e.g. "adhoc reporting" result sets. 

Friday, 27 July 2007

Dell XPS M1710 – Vista Ultimate Upgrade

Further to my last post on Vista and my new Dell M1710 laptop.

As I said before, it came with Home Premium on it. I chose Home Premium because it seemed the logical choice for what I do (see Vista Editions)

What the comparison chart does not tell you is that some useful software won’t run on Premium, for example I came to install Virtual PC 2007, but check out system requirements and low and behold you need Vista Ultimate (despite it being Windows XP Prof compatible)! This is madness. Why should VPC need Ultimate Ed?

Anyway, I needed the software so thought I would “simply upgrade” my Home Premium edition to Ultimate via the much advertised “Vista Windows Anytime Upgrade” facility. So I went online to the Windows Anytime Upgrade site,

It indicated that I needed a windows anytime upgrade compatible Vista install disk, so I checked the Dell Vista DVD and… no official “windows anytime upgrade logo” on it. Daaarn. Would Dell really ship an install DVD that was not “upgrade” compliant?

I went ahead and purchased the Ultimate upgrade online (which automatically downloads/installs a file “product key” ready for upgrading) but played safe and paid the extra £5 for a windows anytime upgrade DVD (posted out) and subsequently closed the windows upgrade. I was assured by a message that I could put the upgrade disc in anytime in the future.

Not being very patient to wait for the DVD to arrive (I still could believe that Dell would not ship an upgrade compliant disk - digging around on the Net confirmed my thinking that all Vista DVDs come with all 6 editions on them), I put in the Dell Vista install disk and got the usual “Windows Vista – Install Now” blue/green screen… no mention of the upgrade though. Was it simply going to install Home Premium again? Aaargh! Did the Ultimate product key register correctly? I reluctantly clicked “install now” (still no mention of the Ultimate upgrade) and went through the install process.

At the end of the install I rebooted and waited with great anticipation to see what had been installed – hooray, Ultimate was now on my machine! It had worked!

So to summarise:

- if you wish to upgrade a Dell M1710 from Home Premium to Ultimate, based on my experience, you do not need to buy a separate Windows Anytime Upgrade DVD (I take no responsibility if your system is different though!)
- Despite the very poor installation wizard user feedback (come on Microsoft how did this get past your usability team?), have faith, your new edition is being installed despite what the user interface implies.

Once upgraded, all worked fine except I had no sound (a common problem with upgrades). Reinstalling the latest sound card drivers from Dell gave no joy either. Uninstalling the drivers and then letting Vista itself install appropriate drivers fixed this though. All is now fine.

Virtual PC 2007 now installs correctly and I can safely take a look at Visual Studio 2008 and .Net 3.5 ;-)

Other Useful link: Windows Anytime Upgrade Installation Overview and FAQ

Thursday, 26 July 2007

Tool for choosing a colour palette

Being more of a techy than a designer, choosing a suitable colour palette for a web site is not exactly my forte.

Here's a tool that can help: http://www.nickherman.com/colormatch/

Define a colour using the RGB sliders and the system will suggest 6 matching colours for you. Works very well.

Thursday, 5 July 2007

Running VS 2005, Oracle 10g client and ODT/ODP.Net on Vista

I've not long received a new laptop (went for the Dell M1710 in the end, not the most portable by any means but a real powerhouse desktop replacement style laptop, just the job when you are running VMs, virtual PCs, Oracle, SQL Server etc all on one machine). Gorgeous 17" screen 1920x1200 which copes nicely with the IDEs of today, although I am not convinced by the current trend of glossy reflective screens - sexy looking they may be but I don't really want to see a reflection of myself whilst coding thank you very much - non-reflective screens (as on my old Inspiron 5150) are much more usable in bright environments. Viewing angles are good though. Came with Vista Home Premium on.

Anyway... once I'd uninstalled all the free 30day trial 'crap' that is installed by default I set out to install all my standard apps that I use day to day.

On the list was of course trusty Visual Studio 2005, along with Oracle 10g client, ODP.Net and Oracle developer tools (ODT).

VS 2005 Prof and SP1 were not a problem, although I did get a couple of "known compatibility issue" pop-ups.

The Oracle versions I'd been using on XP, however were not compatible with Vista (unless you did registry hacks). Oracle have now released officially supported products.

Hence here's what you need if you want Vista compatibility 'out of the box' with Oracle:

Oracle Database 10g Client Release 2 (10.2.0.3)
http://www.oracle.com/technology/software/products/database/oracle10g/htdocs/10203vista.html

Seems to install fine although if you use the Aero interface in Vista you will see a message indicating that the installer is not compatible with that.

ODAC 10.2.0.2.21 (inc. ODP.net plus ODT if you want it) see
http://www.oracle.com/technology/software/tech/windows/odpnet/index.html

Note only the installer has been upgraded to make it compatible with Vista, not the individual ODAC products, so if you are using ODAC 10.2.0.2.20 on another Windows platform (as I do on XP), you don't need to upgrade. See C Shay's article http://cshay.blogspot.com/ for more info.

The above is official released software so can be used in production code.

There is also some nice beta stuff in the pipeline, see 11g stuff http://www.oracle.com/technology/software/tech/windows/odpnet/index_11gbeta.html

Tuesday, 12 June 2007

Live Writer - on/off-line publishing to your blogs

This is worth a look if you blog a lot (still beta):

http://writer.live.com/

Talks to Windows Live Spaces, Sharepoint, WordPress, Blogger, LiveJournal, TypePad, Moveable Type, Community Server plus others. I've not tried it in 'offline mode' yet but online seems to work fine. Just got it working easily with blogger and community server (which needs a little more work, see http://wlwplugins.com/how-to-configure-windows-live-writer-for-community-server.php).
Great for managing multiple blogs.