- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Self-styled database expert?
Admin
There's actually a point to disposing context if you insert many files when using EDMX, but not every time..
Admin
It goes to 11
Admin
Maybe I'm wrong, but IMHO this code actually do what it supposed to do. AFAIK each driver fetch result set from database server in predefined chunks. Unless explicitly specified, driver should use default chunk size. For example Oracle fetch 10 rows.
Also bonus points for closing resources. If not used in multithread environment, I would say it is not WTF, but a radically different approach.
Though if code was designed with this behavior in mind is question. :)
Admin
Better pattern; instead of populating a list, use a callback to process each item as you go. It basically gives the same result as the second block of code, but without any of the same threading and code cleanup issues. Plus if you still want to populate a list, you can provide a callback that does that instead.
Admin
Deal of the week, two WTFs in one! The "we've all written a DAO part", unless your library underneath provides some sort of cursor, is as WTF as the one you're making fun of.
Admin
Should this be interpreted as meaning that the second code snippet is missing some anonymised lines saying
and that the constructor stores its arguments in these static fields?If so, that's arguably a bigger WTF than any of the code that's actually shown. If not, what other variables is it talking about?
Admin
Admin
Where's the problem?
Admin
We've all seen DAOs trying to fetch a million datasets in a object/array.
Admin
I have to say that, apart from using static variables for apparently no reason, I don't see the second code snippet as a worse WTF than the first. In many cases, rather than loading all the data from a dataset into a list/array, it's better to return the dataset object itself and iterate through it.
Admin
Admin
"We've all written a DAO:"
Actually, some of us haven't, and not all of us are familiar with the acronym.
Admin
Admin
issue there is that in java you need to know the size to be able to return a valid container (if you want to conform to the contract)
Admin
DAO: Data Access Object
Admin
sure... and fetch the million datasets again to pick the next ten items.
Admin
I think the best part of this code is how if you don't read all the results of the SELECT, there's no way to tell it to rewind.
So you read rows 1-10, do something with them, and then return because you don't need any more rows. Then the next time through you start with row 11. Which is one row louder.
Admin
who wants to bet that he made those variables static because he (at one point) made the method static and he got a "can't access instance fields inside static method" error
Admin
ummm... who could I ask? Stack Overflow, they might give me a clue.
Admin
I see what he's trying to do, but the way to go about it is to extend ResultSet with a class whose "next" method returns the object, or a List object which - behind the scenes - uses a scrollable result set, maybe even some fancy-pants garbage-collectable reference objects.
Admin
One common approach to the 'get x records from dataset' problem is to approach it from the sql select end:
This selects the 21st to the 30th rows (skip the first 20, give the next 10).
Caching 10 records (or 100, or 1000) instead of the million record dataset can be a much more efficient approach.
Admin
True story
Admin
<looks at self> Yeah, I figured it was an Americanization of "TAO," like zen.
Admin
Apart from the fact that the resultset is static, the function still tries to build an entity and return it to the caller after the resultset has already been closed... and this would certainly throw an exception.
I hope that, at least, the caller then checks if the object returned is not null.
Admin
My bad, I didn't see the return null statement... So I guess in a single-threaded environment, it kind of works, but then I don't see the benefit of using a method instead of simply inlining the code in the caller.
Admin
"He created a dedicated DAO for each and every query."
Presumably the code posted is copy/pasted with various queries in place of ("select ..."). This would create a dedicate dao for each and every query. Then SelectAllDAO or SelectTenDAO or SelectPreviousDAO classes/methods/abominations are created. These are static so that classes from the main program can access any query without needing a reference to each query directly. And without the need for each instance of the main application to create those instances.
We have 500 users using a program. Instead of having those users create 500 different instances of the DAOs the server can handle the instances itself. Of course this could lead to bottlenecking or locking if two or more users try to use the same DAO at the same time.
As for the use of nextrow only the code posted may only be for NextRowDAO. To "rewind" use PreviousRowDAO.
Captcha jumentum //Not touching that one.
Admin
I see what you did there! Nice one :-)
Admin
Admin
and the method was static because he was testing it by running main?
captcha: causa - causa don't know any better
Admin
Unless you use MySQL, in which case the default is to fetch the entire dataset before rs.next() even returns. You have to do some magic incantation to make it stream rows, and even then it only works if you have the right set of client, server, query type, and all sorts of craziness.
How many times have I heard "but it works on my workstation" from developers, and then the code has an OutOfMemory error on the server because someone tries to fetch an n-table join all at once.
Admin
TRWTF is using capital letters at the start of all words in the title of this article, so that people like me who hail from "Reading" now automatically mispronounce the word reading like their own home town.
Admin
Admin
TRWTF is that reading[1] a very common typographical convention is now causing you to pronounce things incorrectly.
[1] No pun intended, I swear
Admin
I think this just fetches 10 random rows and sorts them by name afterwards, because order by is done after limit.
Admin
Those who do not study set theory are doomed to slow queries.
Admin
Ok, DBA, not really been a fecker (front end coder) for many years - but static variables? Am I wrong in thinking this could lead to some stunning data inconsistency wtfs? Or is this a single connection to the database?
Admin
It's the Duh of DAO.
Admin
And now for the soccer results: "Reading One, Row at a Time." Oh do fuck off.
Admin
He never closes his connection, so with a few of these the connection pool will be used up.
Admin
I've noticed that snoofle seems to have been taking the feedback on the comments section seriously and incorporating them into his articles. For instance, this story doesn't have a weird, convoluted background as many of the other ones do. I like that it gets right down to the WTF rather than having a long winded based-on-a-true-story lead in.
Thanks, snoofle!
Admin
'When Jason pointed out that this is not the way to control how much data the server sends back at once, his colleague countered: "But it's only reading one row at a time!"'
In fact, it doesn't. Databases typically send back several thousand rows at once. Doing a round-trip across to the database for every row would be very slow.
Admin
It boils down to perspective. From the perspective of the caller of that method it does "Read" one row at a time. That part is accurate. From the perspective of the database, the underlying connection object and everything else, yes, it does indeed grab it all.
I've seen this type of code before, several times. I keep a list of names in case their resumes come across my desk.
Admin
The problem with selecting rows like that (with limits) is that a data change (in the background) to rows you've already processed can cause you to either select the same row twice (someone inserts a row) or miss rows (someone deletes a row).
Admin
"No you didn't. And this isn't the capital."
"One row at a time, please."
Admin
TRWTF is that DB objects are not closed in the finally block
Admin
The hehavior will always like that unless you get all the records in the database with one query. This side effect may or may not be acceptable behavior for your business use case. For huge database queries, you may need to reconsider to leverage stored procedures.
Admin
I have used this technique with SQL Server with outstanding results. I didn't encounter this, but with other products YMMV.
Admin
Bingo... That's exactly what I was thinking.
Admin