Peet Brits

Hmm, but that doesn’t make sense…

Archive for October, 2008

LINQ: Breaking Your Logic

Posted by Peet Brits on October 18, 2008

LINQ is one of the great new technologies in .NET. As opposed to the frustrations of raw text in XML, I absolutely love how it is strongly typed. I am not going to spend any time discussing its use and features, as there is enough of that on the internet. Instead I will discuss some unexpected behaviours that I recently uncovered.

Without wasting the reader’s time, let me jump straight to the problem. Here is a sample of the filter I would like to apply:

var docs = from doc in db.GetTable()
where doc.Name == interfaceName
&& (filter.Failed.HasValue && doc.Failed.HasValue &&
filter.Failed.Value == doc.Failed.Value)
orderby doc.Name
select doc;

Background: “Failed” is a Nullable bit value both in the code and in the database. I only want to compare and filter if a values has been provided.

This seems like a perfectly acceptable piece of code. The expected C# behaviour for “&&” is that when the first section fails, the following section will not even be evaluated, and therefore it must surely work.

So I thought.

On executing the statement I got the exception “Nullable object must have a value”, originating from line 4 above. I remembered that LINQ translates its logical items to a form of expression tree, so it would seem that all values are always evaluated, regardless of the expected C# behaviour. We need to get rid of “Failed.HasValue”.

No problem, update the filter:

var docs = from doc in db.GetTable()
where doc.Name == interfaceName
&& (filter.Failed.HasValue && doc.Failed.HasValue &&
filter.Failed == doc.Failed)
orderby doc.Name
select doc;

No exception, the query runs through. Only one problem, my result set is empty.

So I evaluate my code again. The first problem is that the query section “filter.Failed == doc.Failed” on line 4 is always evaluated, regardless of whether the first two statements are false.

If that is not enough there is a second problem, regarding what happens when filtering. Once again, take a look at line 4. As it is always evaluated, it would seem that when the filter condition is “null” it evaluates to “null == doc.Failed”, where “doc.Failed” can be true, false, or DBNull.Value. This is clearly not right.

Where to from here? Writing C# functions inside the match is not the answer, as you need to implement translations supported by SQL for the specific section.

The quick and dirty answer is as follows:

// Why not use var? Because the return type keeps on changing.
IQueryable docs = from doc in db.GetTable()
where doc.Name == interfaceName
select doc;

if (filter.Failed.HasValue)
docs = from doc in docs
where filter.Failed == doc.Failed
select doc;

// more filter blocks here

// Finally, remember to sort.
docs = from doc in docs
orderby doc.Name
select doc;

This works fine, but as one might have more than one item to filter on this process might result in a lot of code that needs to be duplicated all over the place. The statement “doc.Failed.HasValue” is also not evaluated, but that is something that can be safely ignored.

On the Microsoft webpage at http://msdn.microsoft.com/en-us/library/bb882535.aspx they give the following advice for handling null values (thanks Marius for providing the link):

// When the parent item might be null,
// the “?:” syntax is not converted to query trees.
(p == null ? null : p.CategoryID)

// When comparing nullable DB values to non-nullable objects,
// box it in a nullable container.
o.EmployeeID equals (int?)e.EmployeeID

That being said, the final product looks as follows:

IQueryable docs = from doc in db.GetTable()
where doc.Name == interfaceName
select doc;

if (filter != null)
{
docs = from doc in docs
where (filter.Failed.HasValue ? filter.Failed == doc.Failed : true)
// && (…) — more filters here
select doc;
}

// Finally, remember to sort.
docs = from doc in docs
orderby doc.Name
select doc;

[Edit: Just for fun I created a follow-up quiz for this article.]

Posted in Code (Programming) | Tagged: , , , | 1 Comment »

Limiting Your Struggles

Posted by Peet Brits on October 5, 2008

All of us have days where our frustrations and struggles completely break our spirits. It is days like that when I begin to wonder why I did not rather become something like a Latin dance instructor. Whatever job you have, there is always some cause of frustration, and in this article I will be taking a closer look to a possible cause of this irritation.

Adding Up

Let me divide it into two sides. The first side we will label “A” and call it struggling. Struggling is something that you do that wastes time, and it becomes frustrating because the more time you spend on it the more you get the feeling that you are not getting anywhere. The frustration is magnified as it usually is something that should just work. An example would be a broken computer software installer. You need to get it working, but you cannot find out why it will not do so. The effect is usually increased by lack of knowledge and tediousness of the process.

On the other side, which we will label “B”, we have challenges. A challenge is something (usually) difficult that you need to overcome, but you are to some extend in control of what is happening and understand and see the progress. An example would be a mathematician solving a mathematical challenge. Usually, as with “A”, it is also something that you need to get done, but is sometimes also done out of sheer enjoyment.

A challenge might seem like a struggle, but it is not. The difference is that when you solve a challenge you feel good about it, but even when you eventually complete the struggle you will still want to throw your PC out of the window because of how stupid it all is.

Now we have two sides of a scale, measured by time and energy invested. The amount that side “B”, the challenges, outweighs side “A”, the struggles, is the amount of job satisfaction that the person perceives. On the other hand, when the first side “A”, the struggles, outweighs side “B”, the challenges, then it will lead to major frustrations, boredom, or even motivation to start looking for a new job.

Balancing Out

It is interesting that these two sides are very much the same. The only real difference is how it is perceived. Further, because different people have different interests, one person’s struggle is sometimes another person’s challenge. To use my example from earlier, the very mathematical problem that is a wonderful challenge for a logical person with mathematical interests will at the same time be an absolute frustration for someone else with no mathematical sense or interest.

As this is not an ideal world we sometimes need to do other people’s unfinished jobs. We need patience for this, but always remember to balance it off with something challenging or fun to maintain a healthy balance. Yes, force yourself to do so. When you notice the warning signs, immediately stop what you are doing for a while, before it is too late.

Posted in Art of Living | Tagged: , , , , | Leave a Comment »