May 2008 - Posts

In this post; I will try to explain use of Recursion method to clear TextBoxes in nested Container Controls.

Below is the Iterative code snippet to clear TextBoxes within any Container Control:
foreach (Control ctl in this.Controls)
{
   if (ctl is TextBox)
      ctl.Text = String.Empty;
}

This code works fine until you insert further / nested GroupBoxes (or any) containers and move the textbox controls into them.
The Controls collection of the form or any other container contains only direct child controls. The contents of nested container controls are not included.
Recursion is the best technique to access a logical tree of unknown depth:

public static void ClearTextboxes(Control container)
{ foreach (Control ctl in container.Controls)
   { var textBox = ctl as TextBox;
      if (textBox != null)
      { textBox.Text = String.Empty; }
      if (ctl.Controls.Count > 0)
      { ClearTextboxes(ctl); }
   }
}

Posted by kaushalparik | 3 comment(s)
Filed under:

Hello Friends,

Below is CSS solution to center your website in ALL Browsers.

/*CSS to BODY TAG*/
body{
    text-align:center;
}

/*CSS to main Container TABLE or DIV or any PlaceHolder TAG of the web page*/
#container{
    width:500px;
    margin-left:auto;
    margin-right:auto;
    text-align:left;
}

 

Posted by kaushalparik | 1 comment(s)
Filed under:

(this is one of the article i posted on our local intranet repository; hope it will be helpful to others)

Web Application Performance (Paging in Sql Server)    

    As a Web developer, you know by now that using the default paging capabilities of ASP.NET Webcontrols like DataGrid and GridView cause the Performance issue when we have thousands and thousands of records in our database; because with every roundtrip to the data-server, you get ALL the records ALL of the time. This is fine perhaps for very small databases. But in web application, you always have to count on its Performance.

    One alternate approach to this scenario is to serve “On Demand” records. That is; for example; retrieving 1-100 records, then 101-200 records result set based on some event rather than retrieving all the records all of the time. I am talking about “Paging in Sql Server”.

My-SQL    

    The simplest solution is provided by My-SQL using LIMIT keyword. Check out the below Query:

    Select * From Product Limits 15,5

    It will retrieve results from 16 to 20 records. In above Query, 15 if the offset from where you want the result set records and 5 is the number of records you want to retrieve.

Sql Server 2005

     Unfortunately, SQL Server does not have an equivalent to “Limit” keyword. Its nearest is TOP N, which returns the first N rows. Still there are two alternative than we can use for “Paging”.

Using ROW_NUMBER()    

    Sql 2005 includes the ROW_NUMBER() function, which adds an integer field to each record. In other words, it adds the record's position within the result set as an additional field so that the first record has a 1, the second a 2, etc.

    To ensure the numbering is consistent, however, SQL Server needs to know how to sort the data. Because of this, ROW_NUMBER() must immediately be followed by the OVER() function. OVER() has one required parameter, which is an ORDER BY clause. The basic syntax is:

SELECT ROW_NUMBER() OVER(ORDER BY [Name]) as RowNum,

[Name], [SKU], [ManufacturerPartNumber]

FROM Product

Paging in Sql Server 

    The Product data in result set will be appeared sorted by Name, and it has an extra column indicating each record's position within the results.

    If we want to limit the results displayed to a certain range, we need to nest this SELECT inside another one. To limit our results to records 5 to 10, we can use the following query:

SELECT * FROM

(SELECT ROW_NUMBER() OVER(ORDER BY [Name]) AS RowNum,

[Name], [SKU], [ManufacturerPartNumber] FROM Product) AS Product1

WHERE RowNum >= 5 AND RowNum <= 10

Paging in Sql Server

 

With Nested Queries    

    There is one another solution that consists only of 1 sql-statement, and so is efficient and quick, even with large databases. The good news is : it will work ! Always ! it's looking rather a bit complicated; but its not!

    Let us see the Example directly to limit our results to records 6 through 10,

SELECT P.[Name], P.[SKU], P.[ManufacturerPartNumber] FROM (

SELECT TOP 5 [ProductID],[Name] FROM (

SELECT TOP 10 [ProductID],[Name]

FROM Product

ORDER BY Product.[Name] ASC) as Product1

ORDER by Product1.[Name] DESC) as Product2

INNER JOIN Product P ON Product2.ProductID = P.ProductID

ORDER by Product2.[Name] ASC

Paging in Sql Server

     Where 5 is the number of rows you want to retrieve and 10 is the offset.

    The innermost Sql Statement will fetch 10 records (1 to 10) Order by Product Name in Ascending Order.

    This means that if you have a table with 10,000 records, and you want to have the last 10 records, the innermost SELECT statement will indeed retrieve 10,000 records. This of course has it's ramifications on performance, but since it's only the primary key fields (which are indexed) and optionally some sort fields, the impact will be minimal.

    The middle Sql Statement will fetch 5 records (10 to 6) Order by Product Name in Descending Order. And Finally the Outer Sql Stateement is simply select statement that will fetch the result in Ascending Order (6 to 10). In Innermost and Midddle Sql Statement only primary key fields or the fields which are indexed are used.

    After looking at this in Query Analyzer, it appears that the extra nesting does not add very much to the load. The SQL statement plays with the sorting orders to limit the records, thus resulting in paged recordsets. This means that there should be at least ONE field to be sorted. If there isn't any, sort on the primary key field(s) !

 

Posted by kaushalparik | 105 comment(s)
Filed under:
Here is a line of T-SQL solution to get comma separated list of values of single field of a database table
 

DECLARE @commaSeparatedVal AS VARCHAR(4000)

SELECT @commaSeparatedVal = ISNULL(@commaSeparatedVal +',','') + CONVERT(VARCHAR,[SKU]) FROM PRODUCT

PRINT @commaSeparatedVal

 

Posted by kaushalparik | 2 comment(s)
Filed under:

   In SQL Server 2008, Microsoft introduces the MERGE functionality through the MERGE command. The MERGE command inserts rows that don’t exist and updates the rows that do exist.

    What MERGE Command works as,

	IF FOUND
THEN UPDATE
ELSE
INSERT;
    Until now, this MERGE functionality could only be made available in SQL Server through stored procedures and cursors, etc.
    This article illustrates how to user MERGE command in SQL Server 2008.
    Suppose we have 2 tables with same field structure as ID, ProductName and SKU, 
	
MERGE INTO ProductTable1 AS Target
USING AS ProductTable2 AS Source
ON Target.ID = Source.ID
WHEN MATCHED THEN
UPDATE SET Target.ProductName = Source.ProductName,
Target.SKU = Source.SKU
WHEN NOT MATCHED THEN
INSERT (ID,ProductName,SKU) VALUES (Source.ID,Source.ProductName,Source.SKU);
Referenced Article:

 

Posted by kaushalparik | 1 comment(s)
Filed under:
Hello Mates,
    Today I am going to buzz on Error Handing in Sql Server 2005.

    The release of Sql Server 2005 has provided us somany features over its predecessor. No doubt that more preference is given to the tasks performed by the administrator. But there are some new development features added to make your Sql Code more powerful and error resistance, specially; Stored Procedures. 

The Feature - “TRY...CATCH” 

    The Most impressive functionality improvement added for developers is “Exceptional Handling” technique. There is no beneficial reason if you are not writing your code in “Try.. Catch” block.

  • A TRY Block - the TRY block contains the code / script that might cause an exception

  • A CATCH Block - if an exception occurs from one of the statements in the TRY block, control is branched to the CATCH block, where the exception can be handled, logged, and so on.

Checking @@ERROR - the “sql 2000” Way of Handling Errors in Stored Procedure

    Just have a look at below Store Procedure example.

CREATE PROC usp_AccountTransaction

@AccountNum INT,

@Amount DECIMAL

AS

BEGIN

BEGIN TRANSACTION --beginning a transaction..

UPDATE MyChecking SET Amount = Amount - @Amount

WHERE AccountNum = @AccountNum

IF @@ERROR != 0 --check @@ERROR variable after each DML statements..

BEGIN

ROLLBACK TRANSACTION --RollBack Transaction if Error..

RETURN

END

ELSE

BEGIN

UPDATE MySavings SET Amount = Amount + @Amount

WHERE AccountNum = @AccountNum

IF @@ERROR != 0 --check @@ERROR variable after each DML statements..

BEGIN

ROLLBACK TRANSACTION --RollBack Transaction if Error..

RETURN

END

ELSE

BEGIN

COMMIT TRANSACTION --finally, Commit the transaction if Success..

RETURN

END

END

END

GO

    Yes!.. This is what we used to code a Stored Procedure in Sql 2000; Check for @@ERROR after every DML (Data Manipulation) Statements and Commit / RollBack the transaction.

    While working with SQL Server 2000, detecting errors could only be handled by checking a global error variable, @@ERROR. Because the @@ERROR variable value is reset after each SQL statement, this leads to rather bloated stored procedures, as the variable must be checked after each statement with code to handle any problems.

    The TRY...CATCH block in SQL Server 2005 offers a much more readable syntax and one that developers are more familiar with. And yes, SQL Server 2005 still supports to @@ERROR Approach. In this article we'll look at the new TRY...CATCH block and examine how it can be used to rollback a transaction in the face of an error. Lets move on to it! 

Handling Errors With SQL Server 2005's TRY...CATCH Blocks

    In Fact, there is really nothing new to be describe and discuss on TRY...CATCH Block; as we all know with any programming languages, TRY...CATCH block executes a number of statements in the TRY block. If there are no errors in any of the statements, control proceeds to after the CATCH block. If, however, one of the statements causes an error, control branches immediately to the start of the CATCH block.

Basic Syntax is,       

BEGIN TRY

Try Statement 1

Try Statement 2

...

Try Statement M

END TRY

BEGIN CATCH

Catch Statement 1

Catch Statement 2

...

Catch Statement N

END CATCH


    The following system functions are available in the CATCH block and can be used to determine additional error information: 
Function                           Description
ERROR_NUMBER()             Returns the number of the error.
ERROR_SEVERITY()           Returns the severity.
ERROR_STATE()                 Returns the error state number.
ERROR_PROCEDURE()       Returns the name of the stored procedure  where the error occurred.
ERROR_LINE()                   Returns the line number inside the routine that caused the error.
ERROR_MESSAGE()            Returns the complete text of the error message.

    Take a look at below example,

BEGIN TRY

SELECT GETDATE()

SELECT 1/0--Evergreen divide by zero example!

END TRY

BEGIN CATCH

SELECT 'There was an error! ' + ERROR_MESSAGE()

RETURN

END CATCH;

Using TRY...CATCH to Rollback a Transaction in the Face of an Error 

    As you saw in earlier example, one of the downsides of the @@ERROR variable approach is that to implement Transaction; we must check this variable after each and every DML SQL statement to determine if an error occurred and, if so, to rollback the transaction. With SQL Server 2005's TRY...CATCH block, however, these types of scripts are greatly simplified.
    Lets Alter the Previous Example!

ALTER PROC usp_AccountTransaction

@AccountNum INT,

@Amount DECIMAL

AS

BEGIN

BEGIN TRY --Start the Try Block..

BEGIN TRANSACTION -- Start the transaction..

UPDATE MyChecking SET Amount = Amount - @Amount

WHERE AccountNum = @AccountNum

UPDATE MySavings SET Amount = Amount + @Amount

WHERE AccountNum = @AccountNum

COMMIT TRAN -- Transaction Success!

END TRY

BEGIN CATCH

IF @@TRANCOUNT > 0

ROLLBACK TRAN --RollBack in case of Error

-- you can Raise ERROR with RAISEERROR() Statement including the details of the exception

RAISERROR(ERROR_MESSAGE(), ERROR_SEVERITY(), 1)

END CATCH

END

GO

    Just look at the simplicity and line of code than previous example!

    In the TRY block a transaction is started and the two UPDATE statements are performed. If both UPDATEs succeed, the COMMIT will be reached and the transaction committed. If, however, either one produces an error, control will be execute CATCH block where the transaction will be rolled back.

    Also, you can “re-raises” the error (using RAISERROR) so that the error information will be passed up to your .Net application from where you are calling the Stored Procedure, in case if you want to use the error information to process further steps anyhow.

    Thats it. lets Code Better!

Referenced Links

Other Functions / Statements Reffered

@@ERROR - Returns the error number for the last Transact-SQL statement executed. Returns 0 if the previous Transact-SQL statement encountered no errors. @@ERROR is cleared and reset on each statement executed

RAISEERROR() - Generates an error message and initiates error processing for the session. RAISERROR can either reference a user-defined message or build a message dynamically. The message is returned as a server error message to the calling application or to an associated CATCH block of a TRY…CATCH construct.

@@TRANCOUNT - The BEGIN TRANSACTION statement increments @@TRANCOUNT by 1. ROLLBACK TRANSACTION decrements @@TRANCOUNT to 0, except for ROLLBACK TRANSACTION savepoint_name, which does not affect @@TRANCOUNT. COMMIT TRANSACTION or COMMIT WORK decrement @@TRANCOUNT by 1.s

 

Posted by kaushalparik | 3 comment(s)
Filed under:

INSERT offers the ability to insert into a table based upon a SELECT statement with the following syntax:

INSERT INTO [TABLEA] ([FIELDA],[FIELDB],[FIELDC])
        SELECT [FIELDA],[FIELDB],[FIELDC]
FROM [TABLEB]


there are time where you may want to do a similar approach with UPDATE.
Here is the syntax to do that very task:

UPDATE [TABLEA]
        SET  [TABLEA].[FIELDA] = [TABLEB].[FIELDA] 
               [TABLEA].[FIELDB] = [TABLEB].[FIELDB] 
               [TABLEA].[FIELDC] = [TABLEB].[FIELDC] 
        FROM [TABLEA]
               JOIN [TABLEB]
        ON [TABLEA].[KEYA] = [TABLEB].[KEYA]

 

 

Posted by kaushalparik | 1 comment(s)
Filed under:

 

One of the cool features of SQL 2008 is Row Constructor. The concept ‘Row Constructors in SQL Server 2008’ basically deals with the crux of multiple inserts performed at one shot. Instead of having to call multiple inserts, we could just insert multiple rows with a single TSQL Statement.

    The following example inserts 3 rows into User Table in a single call. Pay attention to 'VALUES' in the following statement. You just need to specify one INSERT keyword and start filling values separated by comma.

INSERT INTO Product([Name],[ProductSKU],[CreatedDt])
VALUES
('Test Product1', 'CW76548S', '5/12/2008'),
('Test Product2', 'CW98JK76', 6/12/2008'),
('Test Product3', 'CW909876', '7/12/2008')

 

You can also use Row Constructors as a DataSource – On the Fly!

Following is the Example;

SELECT *  FROM 
(
     VALUES
    ('Test Product1', 'CW76548S', '5/12/2008'),
    ('Test Product2', 'CW98JK76', 6/12/2008'),
    ('Test Product3', 'CW909876', '7/12/2008')
) Product([Name],[ProductSKU],[CreatedDt])

Posted by kaushalparik | 3 comment(s)
Filed under:

SQL Server 2008 introduces a TIME data type which allows us to store the time without the date.

For Example,

DECLARE @t TIME = '17:32:19'
SELECT [Time] = @t


Time
----------------
17:32:19.0000000

The TIME data type also allows you to define the accuracy.  This indicates how many places to the right of the decimal are stored for the seconds portion.

DECLARE @t0 TIME(0) = '17:32:19.1234567',
@t7 TIME(7) = '17:32:19.1234567'
SELECT [Time0] = @t0, [Time7] = @t7


Time0 Time7
-------- ----------------
17:32:19 17:32:19.1234567

You can define from zero to seven places to the right of the decimal.  A TIME(0) takes three bytes to store and a TIME(7) takes five bytes to store.  If you declare a TIME variable without the accuracy it defaults to TIME(7).

TIME will do an implicit conversion from DATETIME and retain only the time portion.  TIME will implicitly accept strings in most common time formats.

DECLARE @d1 DATETIME = '12/19/2007 13:43:23.45',
@t1 TIME(2)
SELECT @t1 = @d1
SELECT TimeOnly = @t1


TimeOnly
-----------
13:43:23.45

Reference:    SQLTeam.com. Check Out New data types in SQL Server 2008

 

Posted by kaushalparik | 36 comment(s)
Filed under:

For years now there's been a constant war between Microsoft supporters and Oracle supporters. Oracle has these features, SQL Server has these features, etc. But that's not really where the real importance lies. Sure, functionality is a part of it because your database should be able to do what you need it to do. However, do you want to know what the real difference between the two companies is and why Microsoft has made such a strong impact in the industry?....

Read More..

 

Posted by kaushalparik | 1 comment(s)
Filed under:

Check out the code; how you can upload file to specified FTP Server programatically.

/// <summary>
/// Code to upload file to FTP Server
/// </summary>
/// <param name="strFilePath">Complete physical path of the file to be uploaded</param>
/// <param name="strFTPPath">FTP Path</param>
/// <param name="strUserName">FTP User account name</param>
/// <param name="strPassword">FTP User password</param>
/// <returns>Boolean value based on result</returns>
private bool UploadToFTP(string strFilePath, string strFTPPath, string strUserName, string strPassword)
{
        try
        { 
                //Create a FTP Request Object and Specfiy a Complete Path
                string strFileName = strFilePath.Substring(strFilePath.LastIndexOf("\\") + 1);
                FtpWebRequest reqObj = (FtpWebRequest)WebRequest.Create(strFTPPath + @"/" + strFileName);
                //Call A FileUpload Method of FTP Request Object
                reqObj.Method = WebRequestMethods.Ftp.UploadFile;
                //If you want to access Resourse Protected You need to give User Name and PWD
                reqObj.Credentials = new NetworkCredential(strUserName, strPassword);
                // Copy the contents of the file to the request stream.
                StreamReader sourceStream = new StreamReader(strFilePath);
                byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
                sourceStream.Close();
                reqObj.ContentLength = fileContents.Length;
                Stream requestStream = reqObj.GetRequestStream();
                requestStream.Write(fileContents, 0, fileContents.Length);
                requestStream.Close();
                FtpWebResponse response = (FtpWebResponse)reqObj.GetResponse();
                response.Close();
        }
        catch (Exception Ex)
        {      
// report error
                throw Ex;
        }
        return true;
}

I come accross a code snippet while development which can be useful to convert the date display format.
 

//For ex., Convert MM/dd/YYYY to dd/MM/yyyy

string date = "03/27/2008"; //format is MM/dd/yyyy

DateTimeFormatInfo dateTimeFormatterProvider = DateTimeFormatInfo.CurrentInfo.Clone() as DateTimeFormatInfo;

dateTimeFormatterProvider.ShortDatePattern = "MM/dd/yyyy"; //source date format

DateTime dateTime = DateTime.Parse(date, dateTimeFormatterProvider);

string formatted = dateTime.ToString("dd/MM/yyyy"); //write the format in which you want the date tobe converted

Response.Write("<br />" + formatted);

 

Welcome to the world of Distributed Application!

The article will give you introduction to the world of Distributed Application development and its respective technologies.

What is Remoting?

Remoting” is the process of programs interacting across certain boundaries. The boundaries are either different processes or different machines. In .NET Framework, Remoting can be called the foundation of distributed application.

Remoting implementation generally distinguishes between Remote Objects and Mobile Objects.

Remote Object” provides the facility to execute methods on remote servers. You can pass parameters as well as return values. The “Remote Object” will always “Stay” at server and only a reference to it will be passes around other machines / processes.

While “Mobile Objects” passes the boundary, they are serialized in to some general representation – XML – and then deserialized to the other boundary involved in the process. Both the processes – server and client - hold the copies of the same object. Method execution will always be carried out in local context boundary, and no message will travel back to the process from where the object is actually originated. We can say, there is no distinction between a server object and a client object.

Scenarios for .NET Remoting

I mean, why Remoting comes into picture?

At the beginning of Client/Server era, Remoting was mostly used to access Server Resources; as each database or file server has an implementation which allow code to be executed remotely.

Now-a-days, it’s quite feasible building a distributed application among various machines to improve performance, scalability and maintainability using Remoting.

  • Centralized Business Logic

One of key scenario for remoting implementation is the concentration of business logic on one or more central servers. This simplifies the maintainability and operability of a large-scale application. Because any changes in business logic do not entail you to roll out the application at all user’s end – you just have to update one single server only.

Thus, in this scenario; we need a technique which can be used to communicate in between two process / context boundaries that is the program or process running at user end and another one is running at business server.


  • Physical Separation of Layers

The security is the common concern in web-enabled business. So, general recommendation is against for directly connecting from web server to database server. Instead of that, we used to have one application server / business server as discussed above.


  • Accessing Other Platforms

You will commonly encounter a heterogeneous combination of different platforms, frameworks and programming languages. It is uncommon to find that a bunch of tools, programming languages have been used and implemented to develop an application for a mid-to-large scale enterprise.

Integrating these systems can be a daunting task. Remoting architecture is an absolute necessity in large scale enterprise application integration.


  • Third Party Access

Opening your system for third party access in a business-to-business environment is quite common now-a-days. Application like online Order-entry, which allows third party to place orders from one system to other, is one good example of an application utilizing remoting architecture. More application examples are – address verification system, online price comparison, distributed visitor guard house application etc.

Reference

Advance .NET Remoting by Ingo Rammer

 

Posted by kaushalparik | 1 comment(s)
Filed under:

Article is about:

The ability to pass "a list of values" from .Net as a parameter to a T-SQL based stored procedure.

Scenarios:

There are lots of scenarios where we need to pass a list of values to save in database. 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>)

Some general Approaches:

Taking the INSERT statements as an example, there are various general approaches that we adopt to achieve the desired result:

  • Use dynamic / Inline SQL!  But ideally say, dynamic / Inline 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 we see in various projects, mainly because it is the easiest to implement. The drawback of course is if we were to insert 60 values, it would result in 60 "chatty" calls to the database.
  • 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 the point of this article.

Coming to the main Point, 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.  

Lets take an example. Suppose we are having 2 CheckedListBox; one is list of Users and another is the list of tasks / roles that can be assigned to Users. We want to store the values in Table which is having Fields UserID and TaskID. The Stored Procedure will accept Parameter with XML Datatype as,

CREATE PROCEDURE [dbo].[usp_InsertUserTask]
          @UserTaskXML XML          
AS
BEGIN 
          INSERT INTO UserTasks (UserID,TaskID)
          SELECT    
                      UserTaskTab.UserTaskCol.value('UserID[1]','int') AS UserID,
                      UserTaskTab.UserTaskCol.value('TaskID[1]','int') AS TaskID  
          FROM @UserTaskXML.nodes('//UserTaskList/UserTaskData') AS UserTaskTab(UserTaskCol)
END

To call this in Stored Procedure, you would have something like this:

EXEC    [dbo].[usp_InsertUserTask]
        @UserTaskXML = '<UserTaskList>
                                         <UserTaskData>
                                                 <UserID>1</UserID>
                                                 <TaskID>100</TaskID>
                                         </UserTaskData>              
                                         <UserTaskData>
                                                 <UserID>2</UserID>
                                                 <TaskID>200</TaskID>
                                         </UserTaskData> 
                                </UserTaskList>'

In your application, your C# calling code could be:

        SqlConnection sqlCN = new SqlConnection();
        sqlCN.ConnectionString = ConfigurationManager.AppSettings["DBConn"].ToString();
        string strQuery = "usp_InsertUserTask";
        SqlParameter[] sqlParams = new SqlParameter[1];            
        sqlParams[0] = new SqlParameter("@UserTaskXML", GetStudyDataXMLString());
        SqlHelper.ExecuteNonQuery(sqlCN, CommandType.StoredProcedure, strQuery, sqlParams);
        if (sqlCN.State == ConnectionState.Open)
            sqlCN.Close();
        sqlCN.Dispose();

which calls the method below to translate the UserID and TaskID from CheckBoxLists into an XML String:

private string GetUserTaskListXML()
{
    try
    {            
        StringBuilder XMLString = new StringBuilder();            
        XMLString.AppendFormat("<UserTaskList>");
        for (int iUserCount = 0; iUserCount < UserCheckBoxList.Items.Count; iUserCount++)
        {
            if(UserCheckBoxList.Items[iUserCount].Selected)
            {
                for (int iTaskCount = 0; iTaskCount < TaskCheckBoxList.Items.Count; iTaskCount++)
                {
                    if(TaskCheckBoxList.Items[iTaskCount].Selected)
                    {
                        XMLString.AppendFormat("<UserTaskData>");
                        XMLString.AppendFormat("<UserID>{0}</UserID>", UserCheckBoxList.Items[iUserCount].value);
                        XMLString.AppendFormat("<TaskID>{0}</TaskID>", UserCheckBoxList.Items[iUserCount].value);
                        XMLString.AppendFormat("</UserTaskData>");
                    }
                }
            }
        }
        XMLString.AppendFormat("</UserTaskList>");            
    }
    catch (Exception Ex)
    {
        throw Ex;
    }
    return XMLString.ToString();            
}

Here, StringBuilder is used for the xml concatenation as in this case I think it fits the bill but purists might prefer an XmlTextWriter approach. In summary, it performs very well and is adaptable for various lists of objects and more complex structures.