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); }
}
}
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;
}
(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

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

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

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)
!
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
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:
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
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]
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])
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
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..
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.
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
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.