stepping through a collection in a foreach loop

D

David C

as I've explained to you last time this was posted, for >debugger to display
your fields and properties, it has to invoke it.

As it was found out, not always when the debugger is running. Only when
the autos tab is active, which is not exactly what you said.
 
B

Bruce Wood

I would propose that you create a method, RefreshStudentCourses, or
something like that, and then call it at strategic points throughout
your application.

I find that you usually get cleaner, easier to read, easier to maintain
code by modeling exactly what's going on in real life, rather than
playing tricks behind the scenes.

For example, you could call RefreshFromDatabase(), which in turn calls
RefreshStudentCourses(), every time the user starts a new business
operation, a top-level action.

Another problem with your original solution is that you can't depend
upon your data being self-consistent throughout an entire top-level
operation. Half-way through doing something, you could call your
Course.Students accessor and the list could change, which might put it
out of synch with other data that you've gathered up to that point,
making your top-level operation crash, or, even worse, do subtly wrong
things.

If you have an explicit call to refresh from the database, and call it
at strategic points, you can assume that between those calls your data
will not shift under your feet, which will make your whole program
simpler.
 
D

David C

I would propose that you create
a method, RefreshStudentCourses, or
something like that, and then call
it at strategic points throughout
your application.

I hear you, but that will result in a lot of more methods. For example,
my Course object can have a lot of other collection properties

- Students
- Assigments
- Chairs
- Desks
- TeachingAssistants
- Exams
- Handouts

So are you suggesting a method for every one of those? Surely you don't
want one RefreshFromDataBase() to refresh all of them in one swoop,
because that will make a lot unnecessary trips to all of them only the
only thing you are interested in is, say, Exams.

I would rather do this when I use Students in case you need to retain
it.

students = course.Students;

//at this point, students does not get refreshed
//any more and I can do whatever I want.

Console.Write(students.Count); //no trip to database
Console.Write(course.Students.Count); //a refresh from database
 
B

Bruce Wood

It's not just a case of the debugger not working properly. Refreshing
data on access also makes the application more complex by removing
common assumptions about how code works. Take the following example.

You're looping through the courses for a student, and your loop does
some work (as most loops do). As part of that work, it calls methods
and reads properties on other classes. One the methods on some other
class needs to know what courses a student has, so naturally it invokes
the accessor for student courses. Boom! Your loop now dies randomly
because in the midst of all of this someone else added a new course for
the student to the underlying database.

The lesson here is that you want your internal data to remain stable
throughout a single top-level business operation. Most programmers
simply assume that lists won't be changing at random points in the
code, so making them do so makes the program harder to understand,
because it breaks those common assumptions. Therefore, it's far better
to separate the operation of refreshing internal state, and invoke it
just before you start a new top-level business operation. That way,
your business operation has information at least as recent as the
moment it started, and that information remains stable throughout the
operation.

I don't see that this latter approach introduces any new complexities,
either. True, someone could modify the database between the start of a
business operation and the time you try to write back to the database,
making your write fail (because it violates database constraints, such
as trying to add the same course again for the same student). However,
this would occur even if you refreshed your internal state up to the
moment before you did your update: someone else could still modify the
database in that short moment between your read and your update, so you
have to cope with that, anyway.

You must always assume that any write back to the database could fail
because the database is no longer in a valid state to receive that
update, but you would have to assume that regardless, so extending that
time period back to the beginning of the top-level operation doesn't
introduce any new complexity.
 
B

Bruce Wood

So are you suggesting a method for every one of those?

Well, the code is there anyway, it's just not in a separate method. Is
it really that much more work to move the code into its own method?

In thinking over what you're doing, I would separate the data into
three groups:

1. Reference data that doesn't change. Read this once and cache it for
the duration of the program.

2. Data that could be changed for others, but which is needed for the
"main screen". You need to cache and refresh this.

3. Data that you need in order to do business operations, but which,
once the top-level operation is done, you don't need it any more. I
would read this once at the beginning of the business op, use it to
perform the operation, then throw it away.

So, yes, a method to fetch each kind of information from the DB, then
work with it in memory, then chuck it. Why would you hold it after
you're done one operation ("Add a course to a student," for example),
if you're worried about it going stale? Read it at the start, let it be
invariant throughout the operation, then toss it, and read it again
next time.
 
D

David C

Can't think of any thing to disagree with you on. Would love to see your
code sample to see how you implement these different approaches.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top