|
|
Thu, July 10th, 2008
|
Fun title, huh? Okay, my problem: I'm running NHibernate with cleanly separated layers in a very complex web app. However, the presentation layer needs to allow our users to sort a set of data. It is much quicker and easier to specify the columns in the SortExpression of the presentation controls, but have the data layer and RDBMS do the actual sorting. (Okay, maybe not perfectly separated layers--but it creates more elegant code in the end with less cut & pasting. You'll see...)
So, the presentation layer data access helper methods are allowed to send sort expression and order parameters to the data layer GetByCriteria method. (Side note: I'm using criteria queries here so ICriterion parameters can also be passed to this method. This whole issue either goes away or is different using HSQL or any of the other NHibernate access methods.) That method builds the base criteria query first, then kicks off a recursive function to add the Order criteria. (Side note: Remember, an ICriteria instance is rooted at a table. So if you descend into it with CreateCriteria(), if you have more ICriterion from the method parameters to add, then add them to the original ICriteria--not the returned ICriteria from the calls to CreateCriteria())
And why use a recursive method? Because in the fun ORM world, the objects are nested (as they are normalized of course) from FK to FK. But at the presentation layer, I just wire the controls to the nested properties directly, instead of writing extra wrappers at my presentation layer data access helper classes. Why add all the cut & pasting if the data layer exposes all the properties cleanly already, I figure? I know--I'm mussing up my proper layer separation. But, our clients are usually small businesses, so I have to balance theory with reality and make compromises sometimes.
Back to the recursive method: It splits up the string by periods. (Example: User.FirstName) If this is the only, or last item (example: FirstName), assume it is the actual field. Create the Order and return the ICriteria instance. Simple. Order.Asc(field)--or the Desc version as necessary--you get the idea.
If more then one nesting level was found, first CreateCriteria() to descend into the FK table. Then call this recursive method again, but with this new ICriteria reference (using the ref keyword of course.)
This was an interesting problem to solve, but it worked... Until I came upon a FK that allowed NULLs. Example: A School can have a Manager (User) assigned to it, to give that User special security rights. But a School does not have to have a Manager, and the District has to be the one to manage the School data.
The problem was that as soon as we sorted by this field, all of the rows with NULL values in the FK field disappeared (the entire row, mind you). Why? Because CreateCriteria was descending into the User table but had no FK so it removed the whole row, because... do you know the answer? (It took me a minute to think about it too.)
But I got it: CreateCriteria has overloads. A few of them allow you to specify the JoinType. That's right... I was using the default of an SQL INNER JOIN. I switched to a LEFT OUTER JOIN and bam! Perfect. The rows now sort and NULLs in that FK field just put the row first, but still include them.
And here I was afraid I was just going to have to tell the client too bad--just don't sort on that column or fill in all the Managers. So, I'm all pumped that a very simple solution to a very complex problem came to my feeble little mind so quickly. I got lucky too, because after all these years, I'm still no OUTER JOIN expert.
|
|
|
| |
|
|
| |
|
Tue, June 24th, 2008
|
Nothing new, but for my own reference:
DBCC CHECKIDENT (mytablename, reseed, 16)
|
|
|
| |
|
|
| |
|
|
| |
|
Wed, May 14th, 2008
|
One of my comments got acknowledged by a real, actual Microsoft employee ( who's blog picture looks like Sandra Bullock?) when I pointed out an alternate solution to a problem posited. Wow, what an honor. ;-)
|
|
|
| |
|
Sun, May 11th, 2008
|
Subversion: Not the source code control, but the term. First, read this interesting article at Gamasutra.
My comment on the issue is only an experience I have frrequently: I'm a big TF2 fan. Okay, the situation: I just join a new server and, as usual, start kicking butt. Breaking through enemy lines, destroying the engineer buildings, pushing back rushes, etc. (Not that I don't die in the process some--but I would say my skill is a little above average.) Then, horror, after one of my mad yet effective pyro rushes, my pyro eventually succumbs to attrition and has to respawn. But, a big blue (or red) box pops up saying "You have been switched to the Blue team -- teams have been auto-balanced" or something like that.
At first, I get a little frustrated: "Hey, I picked Red!". And then, I must admit, if the server rules or player counts at the time allow it, I try to switch myself back; heck, that team was probably winning--I want to be back on it to keep dominating. But, if I can't work the system, I submit to my fate. Then, after the realization than now I am on Blue team for good sets in, and I start waiting on the respawn timer. The next phase my mind goes through while I am wiating, is plotting out my next steps when I respawn. "Where is our base and safe spots, and where are the same of the team I was just on? ... Wait, I just destroyed my new team's base. Crap. Why didn't I just dog it when I was back on Red? My new job would have been easier!" You see, this is the idea that surprises me. If you can't be sure your side is the side that should win, should you really give your best effort if it means hurting the side who is the "correct" side?
Not quite as profound as the article, but you get the idea.
|
|
|
| |
|
|
| |
|
Tue, March 25th, 2008
|
I've lived with a minor JavaScript error when using the YUI Container library in Firefox for some time now. I'm an error/warning perfectionist, so this has always irked me a little. I figured I'd Google it in case it has been fixed recently. (When it first came up no one had a workaround.)
The error: Component returned failure code: 0x80470002 (NS_BASE_STREAM_CLOSED) [nsIScriptableInputStream.available]
But, this time I found a workaround on this mailing list. Thanks--it worked for me.
|
|
|
| |
|
Mon, February 25th, 2008
|
ScottGu posted the official, but not fully defined, Silverlight 2.0 feature list. (This is cool--if I can convince a client to fund a project in it, then I am will anxiously, finally, try out writing a Silverlight application myself.)
But in the meantime, I was more interested in the comments. The first thing I did after reading the short blog post, was press slash (/) and type "opera". (For you non-Opera users, that is the quick-find feature.) Why, you ask? To see if anyone complained about the lack of Opera support so far. It is still a second-class browser in most developers minds for some reason, but is still my favorite browser. (Firefox is close to the same browsing experience once you get the many add-ons installed that bring it up to the built-in feature set of Opera, but Opera is still more refined and just generally works better for general browsing, IMO. And a lot fewer memory leak bugs--although, to be fair, those are supposed to be fixed in Firefox 3, which is in beta stage right now.)
Not quite what I was hoping for, but more than I actually expected. Someone did ask, and ScottGu did respond. The response was still, 'eventually, but not yet,' of course. :( However, the new bit of info was that he said that it has actually been coded! And it runs! (Of course it runs--Opera has better support for everything than every other browser. Yes, they usually even beat Firefox and Webkit (Safari) for implementing CSS 3 features, SVG, etc.) Scott just said they haven't done full testing on it yet. Which I think is allowed at this point.
But I'll be quite pleased when they finally release it for my daily browser app... (I wonder if it will work on their embedded versions, like the Wii browser version...?)
Read ScottGu's post
|
|
|
| |
|
|