Archive for January, 2009

From DataReader to Objects

It's been a while since I posted some actual code on my blog.  I'm working on a reporting project at work and ran into a case where I just wanted to execute some arbitrary SQL against an Oracle database and get some plain objects back.  Those objects will be passed into a crystal report and turned into something suitable for digestion by the managament of our company. Nothing fancy here.  

First I'll show you my extension methods and then follow with some explanation:

static Regex underscore = new Regex(@"(^|_)(.)");
static string convertName(string s) {
	return underscore.Replace(s.ToLower(), m => m.Groups[0].ToString().ToUpper().Replace("_",""));
}

static T ToObject<T>(this IDataRecord r) where T:new() {
	T obj = new T();
	for (int i = 0; i < r.FieldCount; i++) {
		var p=typeof(T).GetProperty(convertName(r.GetName(i)));
		if (p != null) {
			if (p.PropertyType == r[i].GetType())
				p.SetValue(obj, r[i], null);
			else {
				var c = TypeDescriptor.GetConverter(r[i]);
				if (c.CanConvertTo(p.PropertyType))
					p.SetValue(obj, c.ConvertTo(r[i],p.PropertyType), null);
			}
		}
	}
	return obj;
}

public static IEnumerable<T> GetObjects<T>(this IDbCommand c) where T : new() {
	using (IDataReader r = c.ExecuteReader()) {
		while (r.Read()) {
			yield return r.ToObject<T>();
		}
	}
}

The meat of the work happens in the extension method for IDataRecord called ToObject.  It's a generic method that tries to map columns to properties.  At our company, the naming convention for column names is underscore delimited identifiers since oracle knows nothing about case unless you use quotes. For my c# objects, I much prefer Pascal Case.  The convertName method gets called to perform this conversion for me.  Finally, the last interesting bit is the TypeDescriptor usage.  When there is a difference in the type coming from the DB and the type in the object for a particular field, I'm using TypeDescriptor to find a converter if possible. This is useful if, for example, the type coming from the DB is a decimal, but my class needs an int.  

The last method, GetObjects is just a wrapper around the ToObject method.  It fires up a datareader and calls ToObject for every row.

Finally, I'd like to show how this is being used. Assume the following silly reporting class.

public class EmployeePerformance{
	public string FirstName {get; set;}
	public string LastName {get; set;}
	public decimal HoursWorked {get; set;}
	public int WidgetsCreated {get; set;}
}

All we have to do now is create a DbCommand object and call our GetObjects extension method.  I'll give an example as if I were running some report just so you have some context.

var rpt=new EmployeePerformanceReport();

using (var cx = new OracleConnection(MyConnectionString)) {
	cx.Open();
	using (var cmd = cx.CreateCommand()) {
		cmd.CommandText = @"
			SELECT
				first_name,
				last_name,
				hours_worked,
				widgets_created
			FROM
				employee_performance
			WHERE
				work_day between :startDate and :endDate
		";
		cmd.Parameters.Add("startDate",new DateTime(2008,1,1));
		cmd.Parameters.Add("endDate",new DateTime(2008,12,31));
		rpt.SetDataSource(cmd.GetObjects<EmployeePerformance>());
	}
}

//Do something with your report

It's just that simple.  I'm sure there could be some caching/compilation of the mapping after the first object to speed things up a bit. Speed hasn't been an issue so far, so I didn't persue that any further. I just wanted to illustrate this technique that lets me avoid using a DataSet which I've come to loathe in most situations. Please let me know what you think.

Are You Selfish Too?

Courtesy of liber

Courtesy of liber

It seems to me that the world is turning into a bunch of selfish bastards.  Sorry to be so blunt, but it's true.  I'm becoming increasingly frustrated with just how self absorbed people are becoming.  No one seems to give a damn about anyone but themselves. If you pay attention, I'm sure you'll see it too.  

When is the last time you went to the store and saw parents letting their kids run amuck tearing things up and leaving messes for the minimum wage employees to clean up?  How many people do you know who have cheated on their spouses? Do you know someone who is stealing from their company?  How many people do you know who cheat on their taxes?  My list can go on here.

Did any of that apply to you?  If so, then you need to stop being an asshole.  The world doesn't revolve around you and it's important you know that you are being a nuisance. Do you know someone like this? If so, I can only recommend that you distance yourself from them as far as you can.  If they are willing to compromise their morals in one area of their life, what makes you think they won't throw you under the bus as soon as it benefits them?  

I'm not trying to push some sort of stupid unicorns pooping lolipops fantasy land where everyone loves each other.  I just want people to be more respectful of others.  Sure, being selfish is a good way to get something in the short term.  In the long run, all it will do is piss everyone off around you and make you die a lonely person.  Think about that for a while.  

Are you willing to "stick it to the man" when you do your taxes just to save a few bucks?  I'm sure that you'll be the very one bitching about your kid's school not running the buses because they have no funding to pay for fuel.  It all comes around full circle and it's going to bite you in the ass eventually.  We all need to give a lot and take a little.  Today it's the other way around and people are just too dependant on getting things for little to nothing.

I don't believe in moral gray areas.  Things are either right or wrong.  If something doesn't feel right, chances are it's because it isn't right.  I do my best to take care of my friends and family.  I try to treat strangers with respect in hopes that they will do the same.  If I took part in some of the things I see happening around me, I would be downright embarrassed. People nowadays just need a little more humility and a lot more honesty.

Hobby of the Month Club

My poor wife knows all to well that I'm a member of the Hobby of the Month Club. Instead of having one particular hobby, I have several! It's a sickness, but I just can't help myself. I just want to learn about everything!

Courtesy of bucklava

Courtesy of bucklava

Here's how it goes: I think I might be getting a new toy. This could be a piece of electronic equipment, power tool, gun, whatever. I'll research the hell out of that particular item on the Internet. Which one is the best? Which one is cheaper? What are the different features? And the most important of all: How much can I customize it? These are the questions that I will obsess agonize over for a month.

After I've made an analysis of my options, then I'll start to second guess myself.  Do I really need this?  Am I going to enjoy it?  Will I be completely satisfied with the product? I HATE having buyer's remorse.  I hate it so much in fact that half the time my research will lead me to not buying that particular item at all.  I just talk myself right out of buying/building it.  Ultimately I'll end up revisiting said product in a year and starting the whole process over again.

Then, here comes the part my wife has to hate.  If I actually commit to buying something, I will then spend the next month playing with it ad nauseum.   If I'm not playing with it, then I'm on a message forum reading about it. My only saving grace is that most of the time Ashley has to convince me to buy something for myself, so she's only doing this to herself. Really, I told you I was sick.

Eventually I'll get bored with giving said item my constant focus and will move onto another item to research, not buy, research, buy, obsess over briefly, and then use like normal.  It's a nasty cycle, but it's who I am.  I like to learn about things and all of the things I can do with said thing.  All I can offer is my deepest apologies to my loving wife who has to put up with this madness.

So, my question to you is: Am I alone here? Surely there are others like me with this same affinity towards learning everything there is to know about a lot of things.

2009 Resolutions

Last year I managed to do fairly well with my goals overall.  I feel good about publicly stating my intentions since it seems to give me a little more motivation to stay on track. 

Health and Fitness

  1. Finish up my damn resolution from 2007 to get down to 250 pounds.  I tried really hard last year, but fell off for the last quarter of the year.  I’m at 275 lbs right now, so I just need to lose 25 more pounds.
  2. Run a 10K.  Last year I did a 5K and it really helped push my weight goals along.  Running a 10K has to work twice as well since it’s twice the distance, right? ;)

Blogging

  1. Grow this blog more.  I really intend on blogging more this year.  I want this blog to not be so much about my weight loss journey.  Simple enough, I’ll just post more about software development.  My goals are to have 250+ subscribers and 200,000 visits by the end of the year. 
  2. Make geekintoshape.com into something.  Last year George and I started a weight loss blog, geek into shape.  My intention was and still is to use that as an outlet for telling the world about my struggles, failures, and successes at losing weight and keeping it off.  I’d like to have 100+ subscribers and 100,000 visits by the end of the year.

Lifestyle

  1. Live simple.  I have a lot of junk and clutter that needs to go away.
  2. Get rid of unnecessary obligations.  There are a lot of things that compete for my attention both in my personal life and in my career.  My goals this year are to focus my efforts to those things which make me happy and to those things which I’m good at.  Anything else needs to be removed, transferred, or outsourced.
  3. Make better use of my idle time.  At the end of the day, I often find myself wondering where the day went.  I know that I can use my time better and get more things done. 

Well, there’s the list.  The lifestyle changes aren’t exactly measurable, but they will be here to serve as a reminder.  Here’s to a positive 2009!