Posts RSS Comments RSS 137 Posts and 272 Comments till now

Using Serialization To Measure .NET DataSet Size

In my previous post, I did commented that serialization could do the trick to measure the size of a DataSet object.

 

I am using both BinaryFormatter and SoapFormatter this time, the code is as follows:

using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Soap;
using System.Runtime.Serialization.Formatters.Binary;

namespace ConsoleApplication1
{
    class Program
    {
        public static int MeasureDataSetByXML(DataSet ds)
        {
            String firstXML = ds.GetXml();
            UnicodeEncoding uniEnc = new UnicodeEncoding();
            return uniEnc.GetByteCount(firstXML);
        }

        public static long MeasureDataSetByBinaryFormatter(DataSet ds)
        {
            return MeasureDataSetSerialization(ds, new BinaryFormatter());
        }

        public static long MeasureDataSetBySoapFormatter(DataSet ds)
        {
            return MeasureDataSetSerialization(ds, new SoapFormatter());
        }

        public static long MeasureDataSetSerialization(DataSet ds, IFormatter formatter)
        {
            FileInfo firstFile = new FileInfo("Test.txt");

            if (firstFile.Exists)
                firstFile.Delete();

            FileStream firstStream = firstFile.OpenWrite();

            //Try Serialize
            try
            {
                formatter.Serialize(firstStream, ds);
                firstStream.Flush();
                firstStream.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed to Serialized. Reason: " + ex.Message);
            }
            //Refresh the FileInfo
            firstFile.Refresh();
            return firstFile.Length;
        }

        static void Main(string[] args)
        {
            //Prepare the Data
            DataSet ds = new DataSet();
            Random r = new Random();
            DataTable dt = new DataTable("TestTable");
            for (int i = 1; i <= 10; i++)
            {
                dt.Columns.Add(new DataColumn("Column_" + i.ToString()));
            }
            dt.AcceptChanges();
            for (int i = 0; i < 10; i++)
            {
                DataRow dr = dt.NewRow();
                foreach (DataColumn dc in dt.Columns)
                {
                    dr[dc.ColumnName] = r.Next(int.MinValue, int.MaxValue).ToString();
                }
                dt.Rows.Add(dr);
            }
            dt.AcceptChanges();
            ds.Tables.Add(dt);
            DataSet firstDataSet = ds.Copy();           

            //Double the Size
            DataTable dt2 = dt.Copy();
            dt2.TableName = "TsetTable";
            ds.Tables.Add(dt2);
            DataSet secondDataSet = ds.Copy();

            Console.WriteLine("DataSet with One Table, measure based on XML: {0} bytes", MeasureDataSetByXML(firstDataSet));
            Console.WriteLine("DataSet with One Table, measure based on Binary Formatter: {0} bytes", MeasureDataSetByBinaryFormatter(firstDataSet));
            Console.WriteLine("DataSet with One Table, measure based on SOAP Formatter: {0} bytes", MeasureDataSetBySoapFormatter(firstDataSet));

            Console.WriteLine("DataSet with Duplicate Tables, measure based on XML: {0} bytes", MeasureDataSetByXML(secondDataSet));
            Console.WriteLine("DataSet with Duplicate Tables, measure based on Binary Formatter: {0} bytes", MeasureDataSetByBinaryFormatter(secondDataSet));
            Console.WriteLine("DataSet with Duplicate Tables, measure based on SOAP Formatter: {0} bytes", MeasureDataSetBySoapFormatter(secondDataSet));

            Console.ReadLine();
        }
    }
}
/* Execution Result: (result may varies with your own run)

DataSet with One Table, measure based on XML: 8086 bytes
DataSet with One Table, measure based on Binary Formatter: 5851 bytes
DataSet with One Table, measure based on SOAP Formatter: 9064 bytes
DataSet with Duplicate Tables, measure based on XML: 16118 bytes
DataSet with Duplicate Tables, measure based on Binary Formatter: 10823 bytes
DataSet with Duplicate Tables, measure based on SOAP Formatter: 16412 bytes

*/

 

What do you think? Which one is the closest to the actual usage of a DataSet object?
Well, I can’t say about the actual RAM usage, but if you are measuring the size of DataSet that you passed to a Web Service, my money is with MeasureDataSetBySoapFormatter

 

How To Determine The Size of .NET DataSet Object in Bytes

Apparently there is no way I haven’t find a way to determine the size of a .NET managed object in memory. The closest I can come out, particularly for a DataSet object is as follows:

DataSet ds = new DataSet();
// ...
// This is where you populate the content of DataSet
// ...
String xmlContent = ds.GetXml();
UnicodeEncoding uniEnc = new UnicodeEncoding();
int byteCount = uniEnc.GetByteCount(xmlContent);

But why we use UnicodeEncoding, not ASCIIEncoding, or UTF8Encoding, well, as MSDN says, String object is a collection of Unicode characters. So if we want to know how many bytes are they, we need to use UnicodeEncoding.

Of course we are still far from our actual objective, but this is a good start. I’ll update as I found other possible method.

Visual Basic 2005 Jumpstart

Today I read this book as I was waiting for my project compiling. This book has been laying on my desk since last Friday. It used to be in laying on one of my colleague desk (untouched! hehehe …. :D ). Anyway, she left my company last Friday, so she passed the book to me (Okay, I did volunteered to provide the book a space in my table :D ). I did first hesitant to receive the book as I am more fond to MSDN Class Library :D You know, just browsing here and there when you stuck at a particular problem.

 

So while my computer bogged down by the compilation process, I gave the book a peek. I skimmed through the pages looking for things that might attract my attention. Unsurprisingly (well.. I did surprised :D ), I realized that I haven’t really dig down all the knowledge (read: language features) about Visual Basic 2005. Here are the things that I learned today:

  1. AndAlso, OrElse keywords. These keywords will help you to short circuit the logic statement. Consider “foo1() AndAlso foo2()”. So if foo1() already returned false, the foo2() statement will not be evaluated. Thus, you increase the execution speed by the complexity of foo2(). And if you use OrElse, foo2() will not be evaluated if foo1() is true. Of course you cannot short circuit the logic statement if your foo2() is doing some kind of processing that you will need to use the result later on.
  2. <Obsolete(”This_Is_Your_Warning_String”)> method attribute. This method attribute helps you generate the compilation warning. So if your colleagues are using your obsolete method, they will see the warning in the compilation log or Visual Studio (Yes my friends, please look at all those warning signs before that Runtime Exception bites your honor in the production server)
  3. My namespace. There are quite many of them. You could check them out HERE. Before today, I don’t know that to download from Internet and save the content to a file can be done just by using this single line of code
    My.Computer.Network.DownloadFile _
        ("http://www.cohowinery.com/downloads/WineList.txt", _
        "C:Documents and SettingsAll UsersDocumentsWineList.txt")
    

    without all the complexity of dealing with Stream Object.

  4. And many more … (my brain short term memory capacity is limited to only three interesting things :D )

After this shocking proof of ignorance wake up call, I think I have been slowing down in my learning process. I am still far away from reaching the top. I am motivated to do better, so should you :D Have a nice reading!

 

PS:The book is good if you’re just started programming in Visual Basic.NET (or thought that you know enough about VB.NET, but apparently you’re not :D ). The flow is structured in such a way that it’s easy for you to either taking a close detailed look, or just skimming through the pages.

 

How To Display HTML Without Saving To File First

The following code will work with the following requirements:

  1. You are using .NET Framework 2.0
  2. You already have WebBrowser control added into your Windows Form
public void DisplayHTML(String strHTML)
{
    if (strHTML != "")
    {
         if (this.webBrowser2.Document != null)
         {
               HtmlDocument doc = this.webBrowser2.Document.OpenNew(true);
               doc.Write(strHTML);
         }
         else
         {
               this.webBrowser2.DocumentText = strHTML;
         }
     }
}

The Woes of Data-Type Conversion

With the current trend of SOI (Service Oriented Architecture), it is very common for Web Application to use Web Service in their back-end. Since the back-end processing is implemented as a Web Service, the Front-End (UI Layer) must convert the data into XML-text before sending it for processing.

 

This conversion from a data-type to xml text, then back to its original data-type, will introduce a pitfall that will plunge many developers into a runtime error. Learning from my past mistakes, I come up with these points that hopefully will save you from experiencing a runtime error (read, an unpleasant call from your customer explaining the problem):

  1. Always check your data before conversion. VB.Net has these functions to help you: IsDBNull(), IsNothing(), IsNumeric(). Use them wisely.
  2. Always initialize a variable before assigning a value.
  3. Try-Catch is there not for nothing.

To illustrate above points, I’ll make a few examples here:

Bad Code:

  Dim i as Integer
  i = Cint(myDataSet.Tables("MyTable").Row(0).("MyValue"))
  ProcessMyVariable(i)

Better Code:

  Dim i as Integer = 0
  If IsNumeric(myDataSet.Tables("MyTable").Row(0).("MyValue")) Then
      i = Cint(myDataSet.Tables("MyTable").Row(0).("MyValue"))
  End If
  ProcessMyVariable(i)

Best Code:

  Dim i as Integer = 0
  Try
      If myDataset.Tables.Contains("MyTable") Then
          If myDataSet.Tables("MyTable").Rows.Count > 0 Then
              If IsNumeric(myDataSet.Tables("MyTable").Row(0).("MyValue")) Then
                  i = Cint(myDataSet.Tables("MyTable").Row(0).("MyValue"))
              End If
          End If
      End If
  Catch e as Exception
  End Try
  ProcessMyVariable(i)

 

Care to add more?

Close
E-mail It
Socialized through Gregarious 42