The Inquisitive Coder - Davy Brion’s Blog

Trying to walk that thin line between intelligence and ignorance

Archive for August, 2008

Batching SqlCommand Queries

Posted by Davy Brion on 31st August 2008

As you know, i always like to reduce unnecessary roundtrips. With my Request/Response service layer and my QueryBatcher for NHibernate, it’s trivially easy to do so. But what if you’re in a situation where you can’t use NHibernate and are stuck with low-level SqlCommands? It’s actually not hard to enable batching those (select) queries either. (note: for insert/update/delete Commands, there is a better way).

People with a lot of straight-up ADO.NET experience probably already know this, but you can simply combine your select statements into one SqlCommand. When you execute that command, you get the results to each of the queries that was in the command. So far, nothing new here. I’m currently using a Data Access Layer at work which creates SqlCommand objects for select queries that you can build up through an API. Obviously, i’d like a way to use each query in whatever way is best for the specific scenario i’m working on. I basically want to be able to execute the SqlCommand objects as a stand-alone query, or in a batch with other queries, without having to modify the code that creates the SqlCommand objects.

So i wrote a SelectCommandCombiner class which allows you to combine multiple SqlCommands into one SqlCommand, while making sure that none of the parameters conflict with each other. Here’s the code:

    public class SelectCommandCombiner

    {

        private readonly List<SqlCommand> commands = new List<SqlCommand>();

 

        public SelectCommandCombiner() : this(new SqlCommand[0]) { }

 

        public SelectCommandCombiner(IEnumerable<SqlCommand> commandsToCombine)

        {

            commands = new List<SqlCommand>();

            if (commandsToCombine != null)

            {

                AddCommands(commandsToCombine);

            }

        }

 

        public void AddCommands(IEnumerable<SqlCommand> commandsToAdd)

        {

            commands.AddRange(commandsToAdd);

        }

 

        public SqlCommand CreateCombinedCommand()

        {

            var combinedCommand = new SqlCommand();

            var combinedCommandText = new StringBuilder();

            var queryIndex = 0;

 

            foreach (var currentCommand in commands)

            {

                var currentCommandText = new StringBuilder(currentCommand.CommandText);

                CreateUniqueParameters(currentCommand, currentCommandText, combinedCommand, queryIndex);

                combinedCommandText.Append(currentCommandText + “;” + System.Environment.NewLine);

                queryIndex++;

            }

 

            combinedCommand.CommandText = combinedCommandText.ToString();

            return combinedCommand;

        }

 

        private static void CreateUniqueParameters(SqlCommand currentCommand, StringBuilder currentCommandText,

            SqlCommand combinedCommand, int queryIndex)

        {

            foreach (SqlParameter parameter in currentCommand.Parameters)

            {

                var clonedParameter = CloneParameter(parameter);

                MakeParameterNameUnique(queryIndex, clonedParameter);

                combinedCommand.Parameters.Add(clonedParameter);

                ReplaceOldNameWithNewName(parameter, clonedParameter, currentCommandText);

            }

        }

 

        private static SqlParameter CloneParameter(ICloneable parameter)

        {

            return (SqlParameter)parameter.Clone();

        }

 

        private static void MakeParameterNameUnique(int queryIndex, SqlParameter clonedParameter)

        {

            var modifiedParameterName = queryIndex + “_” + clonedParameter.ParameterName;

            clonedParameter.ParameterName = modifiedParameterName;

        }

 

        private static void ReplaceOldNameWithNewName(SqlParameter parameter, SqlParameter clonedParameter,

            StringBuilder currentCommandText)

        {

            currentCommandText.Replace(“@” + parameter.ParameterName, “@” + clonedParameter.ParameterName);

        }

    }

Now execute the command returned from the CreateCombinedCommand method and you’ll get all of the results in one roundtrip. There are a couple of ways to deal with the results… you could simply use a DataReader to loop through all the rows of all the result sets:

                var reader = combinedCommand.ExecuteReader();

 

                do

                {

                    while (reader.Read())

                    {

                        // do something with the values in the current row

                    }

                }

                while (reader.NextResult()); // this moves to the next result set

 

                reader.Close();

Or you could use a SqlDataAdapter to fill a DataSet:

                var adapter = new SqlDataAdapter(combinedCommand);

                var dataSet = new DataSet();

                adapter.Fill(dataSet);

 

                foreach (DataTable table in dataSet.Tables)

                {

                    foreach (DataRow row in table.Rows)

                    {

                        // do something with the values

                    }

                }

In a future post, i’ll try to make this as easy to use as the QueryBatcher for NHibernate.

Share/Save/Bookmark

Posted in Performance | 2 Comments »

Recommended Books: Clean Code

Posted by Davy Brion on 30th August 2008

This week i read Robert C. Martin’s Clean Code book. With so many great books already available about writing good code, the first question i asked myself was: do we really need another one? The answer turns out to be YES!

At around 350 pages (depending on which of the appendices you find useful), this book really covers a lot of ground, but in a concise (without being _too_ concise) way. You’ll find the typical sound advice on using good names, writing good functions, good vs bad comments, formatting, abstractions, encapsulation, robustness, integrating third-party code, testing, refactoring, class design, system design, enabling emergent design and dealing with concurrency. After all of that, there are a couple of chapters where existing code is improved step by step. To top it all off, the final chapter contains an extensive list of smells and heuristics.

Some of you are probably thinking that all of this looks rather familiar, especially if you’ve read books like Code Complete, Refactoring and Implementation Patterns. And this book really doesn’t offer anything new that nobody ever wrote about before. It is however the best, and most accessible collection of good advice on good code and design that i’ve read so far.

Share/Save/Bookmark

Posted in Books | 2 Comments »

Tests before code

Posted by Davy Brion on 28th August 2008

A friend pointed me to one of my own posts from over a year ago about why you should write your tests before your code… At that time, i had about 3 readers so it didn’t really get any attention, but i think some people might find it interesting now.

Don’t worry… i’m not going to start recycling my old posts so allow me to get away with this for once ;)

Share/Save/Bookmark

Posted in Test Driven Development | No Comments »

Introducing TDD: How would you do it?

Posted by Davy Brion on 26th August 2008

In about 2 weeks, our Belgian ALT.NET group will give a somewhat large presentation on what ALT.NET is and some of the important concepts and practices. As a part of that presentation, i’ll give a 10 minute ‘lightning-talk’ about TDD. I’ve already got a bit of an idea as to what i’m going to say, but i figured i should ask my readers for some input.

So, if you had to give a short talk (remember, only 10 minutes) about TDD, targeted to an audience that has little to no experience with it, or may not even know anything about it, what are the things you’d really want to highlight? And what are the things that probably aren’t worth mentioning for such a short talk?

Or for those of you who have little to no experience with, or knowledge about TDD, what are the things you’d like to hear if someone were to introduce the concept to you in about 10 minutes?

Share/Save/Bookmark

Posted in ALT.NET, Test Driven Development | 13 Comments »

Why The ALT.NET Community Needs To Change Their Ways

Posted by Davy Brion on 25th August 2008

Since its inception, the ALT.NET community has grown a lot. A lot of people have joined the mailinglists and all over the world local ALT.NET communities have been created, with most likely a lot more on the way. That is definitely a good thing. At the same time though, the ALT.NET community has probably put off as many people (if not more) than it has attracted in the first place.

Now, just so everyone is clear on this: i consider myself a part of that community and i definitely want to see it become successful. But for that to happen, i think we need to make some changes. The biggest problem is that we are often perceived as being elitist, and according to some people closed-minded. And honestly, there’s a lot of truth to that. Just read our mailinglists, our blog posts, our ‘tweets’ (i don’t use twitter so i don’t know if that’s the correct way of referring to it but you know what i mean) and a lot of the material we put out there in general. Not everyone in this community is guilty of it, but a lot of us (myself included) are.

In general, we are extremely opinionated and we often state our opinions with a “our way or the highway” kind of mentality. We often outright dismiss approaches or solutions that do not follow our principles and values. And we usually do it in a manner which comes across in a very negative way. And it’s really not hard to see why that puts a lot of people off. When someone simply tells me i need to do something in a certain way, my natural reflex is to question it. Why should i do it that way? If i don’t get a sound response to that (and one-liners usually don’t cut it), the person (or company or whatever) who made the claim immediately loses credibility in my book. I can definitely see how some people have felt that way after hearing/reading certain ALT.NET people making their claims without properly backing them up or simply brushing off any questioning of those claims.

There is absolutely nothing wrong with being opinionated and voicing those opinions. But we really should try to do so in a more positive manner. Simply stating that all developers should use certain practices or principles just doesn’t work. We have to formulate our messages better and we probably need to provide more material that properly explains why practice X or principle Y or library Z allows us to achieve better results. And most importantly, we need to make sure we’re able to discuss these things with anyone who’s not yet ‘into it’ or even against it, without putting people off. If a lot of people think that we’re elitist, closed-minded, frustrated, annoying, or whatever (and they do, just google it) then we are clearly not doing a good job. If we really want to spread these practices and principles that we value so much, we can’t afford to rub so many people the wrong way.

As i mentioned in the beginning of my post, i’ve definitely made these mistakes on quite a few occasions. And i’m gonna try to change that from now on. So if you see me repeat those mistakes, please direct me to this post :)

Share/Save/Bookmark

Posted in ALT.NET | 12 Comments »

Software Development Books: Investing In Yourself

Posted by Davy Brion on 24th August 2008

I currently have 20 books in my list of recommended books. I’ve read all of those books in the past 2 years, which means i’m averaging about 10 books a year. That’s probably a bit much, and i have to admit i’ve been reading a bit less lately than i used to. But i’ve noticed that a lot of developers that i know hardly ever read books about software development. Which is too bad, because those books really are a cheap way of investing in yourself and your career.

Well, perhaps cheap isn’t the best word to use. After all, some of these books are somewhat expensive, and buying a lot of them certainly adds up. But if you pick the right books, they are usually more than worth the money they cost. Besides, you shouldn’t just look at the price of the book. The most important thing to keep in mind is the knowledge and insight you can get from them. That typically depends on the type of books you buy though. I usually avoid books that are library/framework/language-specific, unless i am very interested in a specific topic.

The books that usually provide the biggest value are the ones that teach you things that you can use in any development environment. It can be about development methodologies, certain concepts or practices, patterns (not just design patterns but architectural patterns, coding patterns, testing patterns, …), as long as the knowledge is reusable. These kinds of books allow you to learn from the experiences of some of the best people in this industry. And the best thing about it is that you can learn a lot from these books in a few days (or weeks), even though it probably took the authors a couple of years to acquire that knowledge and experience. Isn’t that one of the coolest forms of reuse you can think of?

Now obviously, reading a couple of books won’t instantly put you on the same level as the authors, but at the very least it allows you to significantly increase your skills and insight with relatively little effort. And when you start applying that knowledge, you can start reaping the benefits of it pretty soon. It could definitely make your job easier. It most likely will increase the quality of your output at work. It almost certainly increases your value as a software developer.

So do yourself (and everyone else) a favor, and read a good book on software development once in a while. And if you need some help picking out the good books, just look here :)

Share/Save/Bookmark

Posted in Books, Software Development | 10 Comments »

Easing The Pain Of WCF Debugging

Posted by Davy Brion on 20th August 2008

WCF is pretty cool, i guess. It’s quite powerful, and it’s so configurable it even has options to control the speed of the CPU fans of the users of your service. Ok, maybe you can’t really configure that, but with approximately 12.4 billion WCF configuration settings available to you, who knows? But the biggest problem i have with WCF is the painful debugging experience when something goes wrong.

Ever got a client-side exception that looked like this?

[SocketException (0x2746): An existing connection was forcibly closed by the remote host]
System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) +73
System.ServiceModel.Channels.SocketConnection.ReadCore(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout, Boolean closing) +110

[CommunicationException: The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:29:59.8590000'.]
System.ServiceModel.Channels.SocketConnection.ReadCore(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout, Boolean closing) +183
System.ServiceModel.Channels.SocketConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout) +54
System.ServiceModel.Channels.DelegatingConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout) +32
System.ServiceModel.Channels.ConnectionStream.Read(Byte[] buffer, Int32 offset, Int32 count, TimeSpan timeout) +32
System.ServiceModel.Channels.ConnectionStream.Read(Byte[] buffer, Int32 offset, Int32 count) +53
System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count) +37
System.Net.Security.NegotiateStream.StartFrameHeader(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) +131
System.Net.Security.NegotiateStream.StartReading(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) +28
System.Net.Security.NegotiateStream.ProcessRead(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) +223

[IOException: The read operation failed, see inner exception.]
System.Net.Security.NegotiateStream.ProcessRead(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) +333
System.Net.Security.NegotiateStream.Read(Byte[] buffer, Int32 offset, Int32 count) +79
System.ServiceModel.Channels.StreamConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout) +72

[CommunicationException: The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:29:59.8590000'.]
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +7594687
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) +275

Rather messy, no? Does it give you any clue as to what could possibly be wrong? Nope. This particular client-side exception occurs when something goes wrong server-side, at some point after you’ve already returned your return value in your service implementation. Of course, you don’t actually see it happening server-side. So i tried setting IncludeExceptionDetailInFaults to true on the service implementation… didn’t make a difference. I set IncludeExceptionDetailInFaults to true on the service host but that didn’t work either. Sigh.

After some Live Searching (i was actually googling, but let’s make Microsoft think at least someone outside of Redmond uses Live Search) i discovered that you can enable WCF tracing. Bingo! Why didn’t Juval Lowy’s book mention this? It’s supposed to be the WCF Bible…. Oh well, thanks to Google, i mean Live Search, we now know how to enable WCF’s tracing:

  <system.diagnostics>

    <trace autoflush=true />

    <sources>

      <source name=System.ServiceModel

              switchValue=Information, ActivityTracing

              propagateActivity=true>

        <listeners>

          <add name=wcfTraceListener type=System.Diagnostics.XmlWriterTraceListener initializeData=WcfTrace.svclog />

        </listeners>

      </source>

    </sources>

  </system.diagnostics>

You can also use the Service Configuration Editor tool which is available in the Windows SDK, but spare yourself the pain of that tool and just copy/paste this xml in your config file.

Now run the service again, and do whatever it was that triggered the weird client-side exception. After the exception occurred, open the WcfTrace.svclog file with either an editor (it’s not very readable though) or with the Microsoft Service Trace Viewer tool (which is not too bad actually).

When i opened my trace output, i immediately saw a red item in the Activity list… so i clicked on it, and i finally saw the problem:

There was an error while trying to serialize parameter http://tempuri.org/:ProcessReadOnlyRequestsResult. The InnerException message was ‘Maximum number of items that can be serialized or deserialized in an object graph is ‘65536′. Change the object graph or increase the MaxItemsInObjectGraph quota. ‘. Please see InnerException for more details.

There we go… the client-side exception was terribly useless, but this is the best kind of exception: not only is it clear about what’s wrong, it even gives you the solution to the problem. Btw, if you get that client-side exception, it doesn’t mean that your problem will be the same as the one listed here. It could literally be anything if it doesn’t happen inside of your service implementation. I’ve seen the same client-side exception when one type somewhere in the object graph didn’t have a DataContract attribute, for instance.

So anyways, do yourself a favor and enable WCF tracing while you’re still in development… it could save you a lot of time.

Oh and bonus points go to whoever points out which of WCF’s many configuration settings actually make the real exception appear in the client-side stacktrace :)

Share/Save/Bookmark

Posted in WCF | 8 Comments »

Thank you, Visual Studio 2008 SP1

Posted by Davy Brion on 20th August 2008

finally :)

Share/Save/Bookmark

Posted in IDE | 9 Comments »

The CI Build should be a given

Posted by Davy Brion on 19th August 2008

Just read an interesting post by Tim Barcz. It’s about a team struggling to adopt agile practices, and if given a chance to start over, what they should set up first: a CI build or a unit testing process.

I don’t understand why someone would even have to choose between them. Setting up a regular CI build (with that i mean a simple compile + running all the tests) for a project should never take more than 10 minutes, tops. That is assuming that you already have a build server in place, obviously. But with Team City being so incredibly easy to install and configure, that can no longer be an issue.

So what does it take then? Drop in a simple, standard build script which builds your project and runs the tests, add a build configuration and you’re done. Setting up a basic CI build should never take more work than that, unless you have some very specific needs, or the project structure is somewhat messy… as in: it doesn’t compile if you don’t have certain assemblies in folders that are either hardcoded or ‘assumed’ to be there… which should be avoided at all times :)

Seriously though, long build scripts or requiring a lot of time to set up a new CI build are all signs that your CI process in general needs some refracturing (nope, not a typo).

And in case you needed some motivation: even TFS 2008 allows you to set up a CI build in less than 5 minutes of work :)

Share/Save/Bookmark

Posted in Continuous Integration | 2 Comments »

Dealing With Recruiters

Posted by Davy Brion on 18th August 2008

One of the things i dislike the most about being a developer is dealing with recruiters. Even if you’re not listed on any of the job-sites, these people still call you, often in the middle of the workday. I generally feel uncomfortable when you have to deal with a call like that while you’re at work because i don’t want people to think i’m looking for another job (which i’m not). So i keep the sound of my phone off, and i only answer calls from numbers that i have in my contacts or recognize. If i don’t know the number, i divert the call to voicemail (and i don’t really listen to those messages either).

So today i noticed that a certain number tried to call me 4 times. Of course, i don’t pick up. Tonight after work though, i was expecting a call from someone else and i accidentally answered a call from the same number that had tried to call me today. Turns out it was some recruiter.

Him: “Hi I’m So AndSo from DevelopersMeatMarket and i was wondering if you were looking for a new career opportunity”
Me: “Nope, not interested”
Him: “I actually tried calling you a few times today, don’t you even wanna hear me out?”
Me: “Not really… I actually try to avoid recruiters, to be honest”
Him: “Well, you do realize that recruiters are an important part of this business, right? After all, we’re the people who get developers great jobs. Answering those calls is very important for your career.”

owkey… if there’s one thing i dislike more than dealing with recruiters, it’s dealing with recruiters with an attitude.

Me: “Oh really? So tell me, what do you say to your customer when he starts complaining to you that i’m spending too much time dealing with recruiters for my next job?”

At that point he sounds uncomfortable, as if he had no idea how to respond to that.

Me: “Or should i start ignoring other recruiters once i start working for your company?”

Him: “Well, umm… ”

Again, silence.

Me: “Right, i think we can wrap up this conversation… good luck finding somebody”

And then i hung up. When will they learn?

Share/Save/Bookmark

Posted in Off Topic, Rants | 5 Comments »