Question

I was tasked to create code that would fetch data from database using data reader and I'm curious of what is going to be the best practice between the 3 methods that I could use below to convert data from my data reader which by default fetched with a type of object.

    internal static RoomType SelectRoomType(int roomTypeID)
    {
        SqlCommand commRoomTypeSelector = ConnectionManager.MainConnection.CreateCommand();
        commRoomTypeSelector.CommandType = CommandType.StoredProcedure;
        commRoomTypeSelector.CommandText = "Rooms.asp_RMS_RoomType_Select";
        commRoomTypeSelector.Parameters.AddWithValue("RoomTypeID", roomTypeID);

        SqlDataReader dreadRoomType = commRoomTypeSelector.ExecuteReader();
        if (dreadRoomType.FieldCount != 0)
        {
            dreadRoomType.Read();
            RoomType roomType = new RoomType();
            roomType.RoomTypeID = (int)dreadRoomType["RoomTypeID"];
            roomType.RoomTypeName = (string)dreadRoomType["RoomType"];
            roomType.IsActive = ((string)dreadRoomType["IsActive"]).ToUpper() == "Y";
            roomType.LastEditDate = (string)dreadRoomType["LastEditDate"] != string.Empty ? DateTime.Parse((string)dreadRoomType["LastEditDate"]) : DateTime.MinValue;
            roomType.LastEditUser = (string)dreadRoomType["LastEditUser"];
            dreadRoomType.Close();
            return roomType;
        }
        dreadRoomType.Close();
        return null;
    }

What confuses me here is the unboxing part, According to http://msdn.microsoft.com/en-us/library/yz2be5wk.aspx Boxing and Unboxing is quite expensive and should be avoided. I know that i could use

   int.Parse(dreadRoomType["RoomTypeID"].ToString())

instead of

   roomType.RoomTypeID = (int)dreadRoomType["RoomTypeID"];

The question is are there still ways of converting this data in a much more efficient way that both of this option and if there are no possible ways which of the two ways do you prefer to use. Thanks in advance all help and suggestions are accepted :)

Was it helpful?

Solution

You can use SqlDataReader.GetInt32() to avoid having to convert/parse to int again, for this you do have to know at what index the integer is within the columns selected though:

roomType.RoomTypeID = dreadRoomType.GetInt32(0);

OTHER TIPS

Boxing isn't that expensive.

Other alternatives won't help; once you have an object, it's already boxed.
String parsing in particular is probably much more expensive than boxing. (although I haven't measured)

If a typed API exists, you can use it to avoid boxing (eg, calling GetInt32).
(although these typed methods are sometimes just wrappers around the untyped method so that they box too)


Bottom line: Don't worry about it.

That guideline is telling you to avoid boxing things in the first place by using typed (generic) collections where possible

If boxing/unboxing is "slow" (it really isn't)... why would converting to a string and back not be terribly slow? (It really is a waste: boxing/unboxing is significantly faster.) I would first make sure there is a performance problem, before worrying about it, however...

In my experience, for my data, which includes thousands of items loaded at once, I found that much more performance can be gained with pre-determining the column indices (but do so dynamically with GetOrdinal!), and then I don't worry about the rest :)

For one item, as per this post, I wouldn't even worry about ordinals: it's an entirely different use-case and the "expensive" part is talking to the database.

Happy coding.

Boxing and unboxing are not as expensive as parsing a string and extracting an int. Please profile before doing premature optimization.

    private static void GetValue<T>(object o, ref T defaultValue)
    {
        try
        {
            if (defaultValue == null)
            {
                throw new Exception("Default value cannot be null");
            }
            else if (o != null)
            {
                if ((o is T))
                {
                    defaultValue = (T)o;
                }
            }
        }
        catch (Exception)
        {
            throw;
        }
    }

You can use the above method to Convert an object to any basic data type as follows.
Convert to dateTime

    public static DateTime GetDateTime(object o, DateTime defaultValue)
    {
        try
        {
            GetValue<DateTime>(o, ref defaultValue);
            return defaultValue;
        }
        catch (Exception)
        {
            throw;
        }
    }

Convert to Integer

    public static int GetInteger(object o, int defaultValue)
    {
        try
        {
            GetValue<int>(o, ref defaultValue);
            return defaultValue;
        }
        catch (Exception)
        {
            throw;
        }
    }

Refer and download the complete code with all basic data types here http://www.dotnetlines.com/Blogs/tabid/85/EntryId/39/Convert-Object-type-into-its-specific-data-type-using-a-Generic-Method.aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top