why is the second DatabaseConflictException being thrown? - c#

I have some linq2sql stuff which updates some rows.
Then when I submit I do this:
try
{
database.SubmitChanges();
}
catch (ChangeConflictException)
{
database.ChangeConflicts.ResolveAll(RefreshMode.KeepChanges);
database.SubmitChanges();
}
Now the second submit(the one in the catch) is throwing yet again a ChangeConflictException
How is that possible? And if it is possible. How would one need to do the query? (I can not put yet another try/catch around that one? When would I stop?)
I want only the changed values to be put in the database.
EDIT:
let me rephrase the intent of the question: When I say 'ResolveALL(keepchanges)', I would think that I say: "I don't care..just use my values". Instead, it throws yet again the same exception.
I was surprised by this behaviour since the examples on MSDN don't have a second try catch around the second SubmitChanges
So how many times can these exceptions be thrown(As many times as there are columns?), and can I avoid them altogether somehow (after saying ResolveAll)?
EDIT:
Last edit before I start the bounty:
I've made it into a neat loop as suggested by 1 of the commenters. But it doesn't matter how many times I retry. The moment it starts throwing exceptions, it will never do it without an exception! So either it works the first time, or it won't work at all.
Now my linq update has some 20 or 50 rows in it which need updating (I work with batches to speed things up).
Is every resolveall only fixing one issue in 1 column ion 1 row? or is it smart enough to fix everything it encountered?
To recap: the values I just changed (only 1 or 2 columns) are the ones which need to go into the database no matter what. How can I do this using linq (or should I really resort to opening an SqlConnection for this? (If so why Linq in the first place?)
My code up till now:
int retry;
for (retry = 0; retry < 10; retry++)
{
try
{
database.SubmitChanges();
//submit succeeded... break loop
break;
}
catch (ChangeConflictException)
{
database.ChangeConflicts.ResolveAll(RefreshMode.KeepChanges);
if (retry > 0)
{
Thread.Sleep(retry * 10); //introduce some wait, to see if this helps
}
}
EDIT: Found it!
Thanks to the link to the blog in the accepted answer I now cycle through all the conflicts and log them to see what is causing this.
And I'm glad I did, since as it turned out that one of the DB fields contains a trigger which updates something else in certain conditions. So I could resolve as much as I liked, every time the trigger would fire again, causing the next conflict.
This trigger obviously I was not aware off, since my DB admin put it in place there to track something or the other. Triggers can be a great tool, but if you are not aware of them they can cause major headaches!

It may not be picking up on all your conflicts when you call SubmitChanges() (and therefore not resolving them all), because the default behavior is to stop when it reaches the first one.
Try changing
database.SubmitChanges();
to
database.SubmitChanges(ConflictMode.ContinueOnConflict);
See http://arun-ts.blogspot.com/2009/08/linq-to-sql-concurrency-conflicts.html for more info. He also nests two levels of try/catch in his code sample for ResolveAll(), so the second time SubmitChanges() is tried, he's able to log any exception before exiting. That seems like a reasonable model to follow.

If this is something you need to keep retrying, then an obvious reordering of the code is:
bool success = false;
while (!success)
{
try
{
database.SubmitChanges();
success = true;
}
catch (ChangeConflictException)
{
database.ChangeConflicts.ResolveAll(RefreshMode.KeepChanges);
}
}
I don't know much about databases, so I'll stay away from theorising about what your actual problem is, but maybe this will fix it :/

Related

is using while for this ok?

while(player.CloseMenu(menuType))
{
}
player.CloseMenu(menuType) will close one menu of the chosen type, or return false if there are none left of that type.
is it ok to use an empty loop like this to close all the menus of a given type?
Be careful when coming up with clever ways of doing things in code. It may save a few keystrokes in the short run, but someday someone else may look at this code and wonder:
What is this even doing?
Ok, I see what it's doing, but why was it done this way?
Is there a compelling reason for this, and should I avoid it so as to not break something else?
Keep in mind, that someone else may very well be you in several months after you've forgotten the details of this code.
Saving a few lines of code isn't really a big deal. Anything that has to be written only once is a finite amount of work. Anything that sows confusion in support going forward produces an unknown and less finite amount of work.
I'd go with more self documentation in case other people need to read it.
The problem is that you have to infer from the fact that the invocation is inferred as a bool to understand.
Maybe if you named it player.IsMoreAfterClose().
or
while(true)
{
bool b = player.CloseMenu(menuType);
if(!b) break;
}
or
bool b = true;
while(b)
{
b = player.CloseMenu(menuType);
}
I would expand on all of these answers and create a method called CloseAllMenus(MenuType menuType). Then you can put whatever kind of ugly implementation in there, and it will be obvious what it is doing when you call it. Your current code doesn't explain what exactly is happening unless you already know that there can be multiple menus of a particular type open, and that this call will only close one of them.
It'll work, obviously, but it makes the code a little hard to read/maintain. You might be better of with the loop condition being a check for any open menus, with the body of the loop closing one.
It's ok to do that as it means do something until certain condition is met. But it's better to incorporate that in the CloseMenu function so that you don't have to repeat this instruction many times and in fact it's a variation of closing menu where you want to close all menus. You can add a boolean argument to the function to indicate if you want to close all menus.
bool CloseMenu(type, closeAll){
if(closeAll)
while(exists(type))
{ close...
else
if(exists(type)
{ close...
}
Maybe the "right" thing to do is invert from While/Close with no body to For/Open with the body doing the Close operation.
foreach(var menu in player.OpenMenus)
menu.Close();
or:
player.OpenMenus.ForEach(c => c.Close());

how to use exceptions in this scenario?

I have a method which handles a set of records.This method,return true\false after processing.So,if all the records are processed(doing some db updates),will return true.Now,suppose after processing 1 record,some exception is thrown,should I write result=false(at the end of method result is returned) in catch block? And,allow processing of other records to be done?
Continuing to add data to the dbase when adding one record failed is almost always wrong. Records are very frequently related. They represent a set of transactions on a bank account. Or a batch of orders from a customer. Adding these with one of them missing is always a problem.
Not only do you give your client a huge problem coming up with a new batch that contains the single corrected record, you make it far too easy to allow somebody to just ignore the error. The kind of error that doesn't get discovered or causes problems until much later. Invariably with a huge cost associated with correcting the error.
When an error occurs, reject the entire batch. Keep the dbase in a proper state by using transactions. Use, say, SqlTransaction and call BeginTransaction() when you start. Call Commit() when everything worked, call Rollback() in your catch clause.
Your client can now go back to the sub-system that generates the records, make the correction and re-run your program. Your dbase will always contain a proper copy of that sub-system's data. And errors cannot be ignored.
How you handle this with exceptions will be determined very much by what you want to happen in the event of something going wrong. You could, as you say, just write result= false in your catch blocks, but this means you are simply saying to the calling function "Hey - some records were not processed - live with it...". That might be enough for you - it depends what you're trying to do.
At the very least though, I would want to also write the details of the exceptions away to a log. And if you don't have a method somewhere that takes an exception and writes away to a log, it's time to write one (or use a third party solution...)
Otherwise you are losing information that could be useful in determining why things failed...
Whether you process those records you can or throw everything out in the event of a problem is a design question that only you can answer - we don't have the context...
I think it could be something like that
int count = 0;
foreach( item in list)
{
try
{
//update DB
++count;
}
catch(Exception ex)
{
//log exception
}
if(count == list.Count)
return true;
else return false;
}
Another way
bool result = true;
foreach( item in list)
{
try
{
//update DB
}
catch(Exception ex)
{
//log exception
result = false;
}
return result;
}

Handling exceptions vs. Preventing them from occuring in the first place - C#

I have a asp:BoundColumn with DateTime? data (i'll call it column X) in the asp:GridView. I loop through all the rows in the grid, and cast the .Text property to column X to DateTime (i need this to do some checking and change the cell background color if needed).
I have 2 options:
wrap the cast in try/catch ... handle FormatException (in case column X gets rendered with some junk in it) ... and work only with valid DateTime values.
check the column X to make sure it's
in the correct format (how?) before
casing, and only cast if format is
ok.
Which approach should i take, and why?
Thank you.
p.s. 1 up-vote for all explanations, accepted answer for TryParse
Edit2: even though i used TryParse, I've unchecked the accepted answer to keep the discussion going.
My "good data"/"bad data" ratio is about 2/1 - this means lots of bad input
I'll re-accept the answer in a couple of days, if nothing else comes up.
You could do the 2nd option. DateTime.TryParse can help.
I think it depends a bit on how often you expect it to be in the wrong format. Wrapping something in a try-catch doesn't really have any impact at all if the exception is seldom raised. But if you expect it to be raised, a lot, then you should maybe add a check to it.
I would go for the second option. I never use exceptions for regular code, because then I can run with the visual studio option "break into debugger when exception is thrown".
This saves me a lot of time when identifying real problems in code, because the debugger will stop at the actual problem instead of somewhere else. If exceptions are used for non-problematic issues I cannot do this reliably.
Exceptions take a lot of resources to raise and catch. You should avoid letting them be thrown when there are more elegant options available.
A rule I follow: Always try to catch as many errors manually as you can, and use exceptions as a last resort.
Exceptions have an impact on performance.
One thing to note is that "TryParse" will not necessarily be better performance than having a Try Catch around your "Parse".
It depends on your failure rate. Try-Catch's have a performance impact, although most of the impact is when you fail.
However, if you have a 95% success rate, or even higher, and performance is a consideration, then you might want to think about wrapping your loop in a try-catch, so that you only hit your "try" statement when there's a failure.
int i = 0;
List<String> prePopulated;
List<DateTime> toPopulate;
while(i < prepopulated.Length)
{
Try
{
while(i < prepopulated.Length)
{
List<DateTime>.add(DateTime.Parse(prePopulated[i]));
i++;
}
}
Catch(Exception ex)
{
//log if necessary
i++;
}
}
Keep in mind, that solution is only better if your data is primarily clean and performance is key.
Otherwise, the simpler one line "TryParse" is better.
I agree with DateTime.TryParse. I work on a very high volume site and we're not allowed to catch exceptions in the UI, ever!, which helps us to prevent bugs. We try really hard to make sure the code we're calling cannot throw exceptions.

Try-catch every line of code without individual try-catch blocks

I do not currently have this issue, but you never know, and thought experiments are always fun.
Ignoring the obvious problems that you would have to have with your architecture to even be attempting this, let's assume that you had some horribly-written code of someone else's design, and you needed to do a bunch of wide and varied operations in the same code block, e.g.:
WidgetMaker.SetAlignment(57);
contactForm["Title"] = txtTitle.Text;
Casserole.Season(true, false);
((RecordKeeper)Session["CasseroleTracker"]).Seasoned = true;
Multiplied by a hundred. Some of these might work, others might go badly wrong. What you need is the C# equivalent of "on error resume next", otherwise you're going to end up copying and pasting try-catches around the many lines of code.
How would you attempt to tackle this problem?
public delegate void VoidDelegate();
public static class Utils
{
public static void Try(VoidDelegate v) {
try {
v();
}
catch {}
}
}
Utils.Try( () => WidgetMaker.SetAlignment(57) );
Utils.Try( () => contactForm["Title"] = txtTitle.Text );
Utils.Try( () => Casserole.Season(true, false) );
Utils.Try( () => ((RecordKeeper)Session["CasseroleTracker"]).Seasoned = true );
Refactor into individual, well-named methods:
AdjustFormWidgets();
SetContactTitle(txtTitle.Text);
SeasonCasserole();
Each of those is protected appropriately.
I would say do nothing.
Yup thats right, do NOTHING.
You have clearly identified two things to me:
You know the architecture is borked.
There is a ton of this crap.
I say:
Do nothing.
Add a global error handler to send you an email every time it goes boom.
Wait until something falls over (or fails a test)
Correct that (Refactoring as necessary within the scope of the page).
Repeat every time a problem occurs.
You will have this cleared up in no time if it is that bad. Yeah I know it sounds sucky and you may be pulling your hair out with bugfixes to begin with, but it will allow you to fix the needy/buggy code before the (large) amount of code that may actually be working no matter how crappy it looks.
Once you start winning the war, you will have a better handle on the code (due to all your refactoring) you will have a better idea for a winning design for it..
Trying to wrap all of it in bubble wrap is probably going to take just a long to do and you will still not be any closer to fixing the problems.
It's pretty obvious that you'd write the code in VB.NET, which actually does have On Error Resume Next, and export it in a DLL to C#. Anything else is just being a glutton
for punishment.
Fail Fast
To elaborate, I guess I am questioning the question. If an exception is thrown, why would you want your code to simply continue as if nothing has happened? Either you expect exceptions in certain situations, in which case you write a try-catch block around that code and handle them, or there is an unexpected error, in which case you should prefer your application to abort, or retry, or fail. Not carry on like a wounded zombie moaning 'brains'.
This is one of the things that having a preprocessor is useful for. You could define a macro that swallows exceptions, then with a quick script add that macro to all lines.
So, if this were C++, you could do something like this:
#define ATTEMPT(x) try { x; } catch (...) { }
// ...
ATTEMPT(WidgetMaker.SetAlignment(57));
ATTEMPT(contactForm["Title"] = txtTitle.Text);
ATTEMPT(Casserole.Season(true, false));
ATTEMPT(((RecordKeeper)Session["CasseroleTracker"]).Seasoned = true);
Unfortunately, not many languages seem to include a preprocessor like C/C++ did.
You could create your own preprocessor and add it as a pre-build step. If you felt like completely automating it you could probably write a preprocessor that would take the actual code file and add the try/catch stuff in on its own (so you don't have to add those ATTEMPT() blocks to the code manually). Making sure it only modified the lines it's supposed to could be difficult though (have to skip variable declarations, loop constructs, etc to that you don't break the build).
However, I think these are horrible ideas and should never be done, but the question was asked. :)
Really, you shouldn't ever do this. You need to find what's causing the error and fix it. Swallowing/ignoring errors is a bad thing to do, so I think the correct answer here is "Fix the bug, don't ignore it!". :)
On Error Resume Next is a really bad idea in the C# world. Nor would adding the equivalent to On Error Resume Next actually help you. All it would do is leave you in a bad state which could cause more subtle errors, data loss and possibly data corruption.
But to give the questioner his due, you could add a global handler and check the TargetSite to see which method borked. Then you could at least know what line it borked on. The next part would be to try and figure out how to set the "next statement" the same way the debugger does it. Hopefully your stack won't have unwound at this point or you can re-create it, but it's certainly worth a shot. However, given this approach the code would have to run in Debug mode every time so that you would have your debug symbols included.
As someone mentioned, VB allows this. How about doing it the same way in C#? Enter trusty reflector:
This:
Sub Main()
On Error Resume Next
Dim i As Integer = 0
Dim y As Integer = CInt(5 / i)
End Sub
Translates into this:
public static void Main()
{
// This item is obfuscated and can not be translated.
int VB$ResumeTarget;
try
{
int VB$CurrentStatement;
Label_0001:
ProjectData.ClearProjectError();
int VB$ActiveHandler = -2;
Label_0009:
VB$CurrentStatement = 2;
int i = 0;
Label_000E:
VB$CurrentStatement = 3;
int y = (int) Math.Round((double) (5.0 / ((double) i)));
goto Label_008F;
Label_0029:
VB$ResumeTarget = 0;
switch ((VB$ResumeTarget + 1))
{
case 1:
goto Label_0001;
case 2:
goto Label_0009;
case 3:
goto Label_000E;
case 4:
goto Label_008F;
default:
goto Label_0084;
}
Label_0049:
VB$ResumeTarget = VB$CurrentStatement;
switch (((VB$ActiveHandler > -2) ? VB$ActiveHandler : 1))
{
case 0:
goto Label_0084;
case 1:
goto Label_0029;
}
}
catch (object obj1) when (?)
{
ProjectData.SetProjectError((Exception) obj1);
goto Label_0049;
}
Label_0084:
throw ProjectData.CreateProjectError(-2146828237);
Label_008F:
if (VB$ResumeTarget != 0)
{
ProjectData.ClearProjectError();
}
}
Rewrite the code. Try to find sets of statements which logically depend on each other, so that if one fails then the next ones make no sense, and hive them off into their own functions and put try-catches round them, if you want to ignore the result of that and continue.
This may help you in identifing the pieces that have the most problems.
# JB King
Thanks for reminding me. The Logging application block has a Instrumentation Event that can be used to trace events, you can find more info on the MS Enterprise library docs.
Using (New InstEvent)
<series of statements>
End Using
All of the steps in this using will be traced to a log file, and you can parse that out to see where the log breaks (ex is thrown) and id the high offenders.
Refactoring is really your best bet, but if you have a lot, this may help you pinpoint the worst offenders.
You could use goto, but it's still messy.
I've actually wanted a sort of single statement try-catch for a while. It would be helpful in certain cases, like adding logging code or something that you don't want to interrupt the main program flow if it fails.
I suspect something could be done with some of the features associated with linq, but don't really have time to look into it at the moment. If you could just find a way to wrap a statement as an anonymous function, then use another one to call that within a try-catch block it would work... but not sure if that's possible just yet.
If you can get the compiler to give you an expression tree for this code, then you could modify that expression tree by replacing each statement with a new try-catch block that wraps the original statement. This isn't as far-fetched as it sounds; for LINQ, C# acquired the ability to capture lambda expressions as expression trees that can be manipulated in user code at runtime.
This approach is not possible today with .NET 3.5 -- if for no other reason than the lack of a "try" statement in System.Linq.Expressions. However, it may very well be viable in a future version of C# once the merge of the DLR and LINQ expression trees is complete.
Why not use the reflection in c#? You could create a class that reflects on the code and use line #s as the hint for what to put in each individual try/catch block. This has a few advantages:
Its slightly less ugly as it doesn't really you require mangle your source code and you can use it only during debug modes.
You learn something interesting about c# while implementing it.
I however would recommend against any of this, unless of course you are taking over maintance of someelses work and you need to get a handle on the exceptions so you can fix them. Might be fun to write though.
Fun question; very terrible.
It'd be nice if you could use a macro. But this is blasted C#, so you might solve it with some preprocessor work or some external tool to wrap your lines in individual try-catch blocks. Not sure if you meant you didn't want to manually wrap them or that you wanted to avoid try-catch entirely.
Messing around with this, I tried labeling every line and jumping back from a single catch, without much luck. However, Christopher uncovered the correct way to do this. There's some interesting additional discussion of this at Dot Net Thoughts and at Mike Stall's .NET Blog.
EDIT: Of course. The try-catch / switch-goto solution listed won't actually compile since the try labels are out-of-scope in catch. Anyone know what's missing to make something like this compile?
You could automate this with a compiler preprocess step or maybe hack up Mike Stall's Inline IL tool to inject some error-ignorance.
(Orion Adrian's answer about examining the Exception and trying to set the next instruction is interesting too.)
All in all, it seems like an interesting and instructive exercise. Of course, you'd have to decide at what point the effort to simulate ON ERROR RESUME NEXT outweighs the effort to fix the code. :-)
Catch the errors in the UnhandledException Event of the application. That way, unhandled execptions can even be logged as to the sender and whatever other information the developer would reasonable.
Unfortunately you are probably out of luck. On Error Resume Next is a legacy option that is generally heavily discouraged, and does not have an equivalent to my knowledge in C#.
I would recommend leaving the code in VB (It sounds like that was the source, given your specific request for OnError ResumeNext) and interfacing with or from a C# dll or exe that implements whatever new code you need. Then preform refactoring to cause the code to be safe, and convert this safe code to C# as you do this.
You could look at integrating the Enterprise Library's Exception Handling component for one idea of how to handle unhandled exceptions.
If this is for ASP.Net applications, there is a function in the Global.asax called, "Application_Error" that gets called in most cases with catastrophic failure being the other case usually.
Ignoring all the reasons you'd want to avoid doing this.......
If it were simply a need to keep # of lines down, you could try something like:
int totalMethodCount = xxx;
for(int counter = 0; counter < totalMethodCount; counter++) {
try {
if (counter == 0) WidgetMaker.SetAlignment(57);
if (counter == 1) contactForm["Title"] = txtTitle.Text;
if (counter == 2) Casserole.Season(true, false);
if (counter == 3) ((RecordKeeper)Session["CasseroleTracker"]).Seasoned = true;
} catch (Exception ex) {
// log here
}
}
However, you'd have to keep an eye on variable scope if you try to reuse any of the results of the calls.
Hilite each line, one at a time, 'Surround with' try/catch. That avoids the copying pasting you mentioned

Does This ASP.NET Consultant Know What He's Doing?

The IT department of a subsidiary of ours had a consulting company write them an ASP.NET application. Now it's having intermittent problems with mixing up who the current user is and has been known to show Joe some of Bob's data by mistake.
The consultants were brought back to troubleshoot and we were invited to listen in on their explanation. Two things stuck out.
First, the consultant lead provided this pseudo-code:
void MyFunction()
{
Session["UserID"] = SomeProprietarySessionManagementLookup();
Response.Redirect("SomeOtherPage.aspx");
}
He went on to say that the assignment of the session variable is asynchronous, which seemed untrue. Granted the call into the lookup function could do something asynchronously, but this seems unwise.
Given that alleged asynchronousness, his theory was that the session variable was not being assigned before the redirect's inevitable ThreadAbort exception was raised. This faulure then prevented SomeOtherPage from displaying the correct user's data.
Second, he gave an example of a coding best practice he recommends. Rather than writing:
int MyFunction(int x, int x)
{
try
{
return x / y;
}
catch(Exception ex)
{
// log it
throw;
}
}
the technique he recommended was:
int MyFunction(int x, int y, out bool isSuccessful)
{
isSuccessful = false;
if (y == 0)
return 0;
isSuccessful = true;
return x / y;
}
This will certainly work and could be better from a performance perspective in some situations.
However, from these and other discussion points it just seemed to us that this team was not well-versed technically.
Opinions?
Rule of thumb: If you need to ask if a consultant knows what he's doing, he probably doesn't ;)
And I tend to agree here. Obviously you haven't provided much, but they don't seem terribly competent.
I would agree. These guys seem quite incompetent.
(BTW, I'd check to see if in "SomeProprietarySessionManagementLookup," they're using static data. Saw this -- with behavior exactly as you describe on a project I inherited several months ago. It was a total head-slap moment when we finally saw it ... And wished we could get face to face with the guys who wrote it ... )
If the consultant has written an application that's supposed to be able to keep track of users and only show the correct data to the correct users and it doesn't do that, then clearly something's wrong. A good consultant would find the problem and fix it. A bad consultant would tell you that it was asynchronicity.
On the asynchronous part, the only way that could be true is if the assignment going on there is actually an indexer setter on Session that is hiding an asynchronous call with no callback indicating success/failure. This would seem to be a HORRIBLE design choice, and it looks like a core class in your framework, so I find it highly unlikely.
Usually asynchronous calls have a way to specify a callback so you can determine what the result is, or if the operation was successful. The documentation for Session should be pretty clear though on if it is actually hiding an asynchronous call, but yeah... doesn't look like the consultant knows what he is talking about...
The method call that is being assigned to the Session indexer cannot be asynch, because to get a value asynchronously, you HAVE to use a callback... no way around that, so if there is no explicit callback, it's definitely not asynch (well, internally there could be an asynchronous call, but the caller of the method would perceive it as synchronous, so it is irrelevant if the method internally for example invokes a web service asynchronously).
For the second point, I think this would be much better, and keep the same functionality essentially:
int MyFunction(int x, int y)
{
if (y == 0)
{
// log it
throw new DivideByZeroException("Divide by zero attempted!");
}
return x / y;
}
For the first point, that does indeed seem bizarre.
On the second one, it's reasonable to try to avoid division by 0 - it's entirely avoidable and that avoidance is simple. However, using an out parameter to indicate success is only reasonable in certain cases, such as int.TryParse and DateTime.TryParseExact - where the caller can't easily determine whether or not their arguments are reasonable. Even then, the return value is usually the success/failure and the out parameter is the result of the method.
Asp.net sessions, if you're using the built-in providers, won't accidentally give you someone else's session. SomeProprietarySessionManagementLookup() is the likely culprit and is returning bad values or just not working.
Session["UserID"] = SomeProprietarySessionManagementLookup();
First of all assigning the return value from an asynchronously SomeProprietarySessionManagementLookup() just wont work. The consultants code probably looks like:
public void SomeProprietarySessionManagementLookup()
{
// do some async lookup
Action<object> d = delegate(object val)
{
LookupSession(); // long running thing that looks up the user.
Session["UserID"] = 1234; // Setting session manually
};
d.BeginInvoke(null,null,null);
}
The consultant isn't totally full of BS, but they have written some buggy code. Response.Redirect() does throw a ThreadAbort, and if the proprietary method is asynchronous, asp.net doesn't know to wait for the asynchronous method to write back to the session before asp.net itself saves the session. This is probably why it sometimes works and sometimes doesn't.
Their code might work if the asp.net session is in-process, but a state server or db server wouldn't. It's timing dependent.
I tested the following. We use state server in development. This code works because the session is written to before the main thread finishes.
Action<object> d = delegate(object val)
{
System.Threading.Thread.Sleep(1000); // waits a little
Session["rubbish"] = DateTime.Now;
};
d.BeginInvoke(null, null, null);
System.Threading.Thread.Sleep(5000); // waits a lot
object stuff = Session["rubbish"];
if( stuff == null ) stuff = "not there";
divStuff.InnerHtml = Convert.ToString(stuff);
This next snippet of code doesn't work because the session was already saved back to state server by the time the asynchronous method gets around to setting a session value.
Action<object> d = delegate(object val)
{
System.Threading.Thread.Sleep(5000); // waits a lot
Session["rubbish"] = DateTime.Now;
};
d.BeginInvoke(null, null, null);
// wait removed - ends immediately.
object stuff = Session["rubbish"];
if( stuff == null ) stuff = "not there";
divStuff.InnerHtml = Convert.ToString(stuff);
The first step is for the consultant to make their code synchronous because their performance trick didn't work at all. If that fixes it, have the consultant properly implement using the Asynchronous Programming Design Pattern
I agree with him in part -- it's definitely better to check y for zero rather than catching the (expensive) exception. The out bool isSuccessful seems really dated to me, but whatever.
re: the asynchronous sessionid buffoonery -- may or may not be true, but it sounds like the consultant is blowing smoke for cover.
Cody's rule of thumb is dead right. If you have to ask, he probably doesn't.
It seems like point two its patently incorrect. .NET's standards explain that if a method fails it should throw an exception, which seems closer to the original; not the consulstant's suggestion. Assuming the exception is accurately & specifically describing the failure.
The consultants created the code in the first place right? And it doesn't work. I think you have quite a bit of dirt on them already.
The asynchronous answer sounds like BS, but there may be something in it. Presumably they have offered a suitable solution as well as pseudo-code describing the problem they themselves created. I would be more tempted to judge them on their solution rather than their expression of the problem. If their understanding is flawed their new solution won't work either. Then you'll know they are idiots. (In fact look round to see if you have a similar proof in any other areas of their code already)
The other one is a code style issue. There are a lot of different ways to cope with that. I personally don't like that style, but there will be circumstances under which it is suitable.
They're wrong on the async.
The assignment happens and then the page redirects. The function can start something asynchronously and return (and could even conceivably alter the Session in its own way), but whatever it does return has to be assigned in the code you gave before the redirect.
They're wrong on that defensive coding style in any low-level code and even in a higher-level function unless it's a specific business case that the 0 or NULL or empty string or whatever should be handled that way - in which case, it's always successful (that successful flag is a nasty code smell) and not an exception. Exceptions are for exceptions. You don't want to mask behaviors like this by coddling the callers of the functions. Catch things early and throw exceptions. I think Maguire covered this in Writing Solid Code or McConnell in Code Complete. Either way, it smells.
This guy does not know what he is doing. The obvious culprit is right here:
Session["UserID"] = SomeProprietarySessionManagementLookup();
I have to agree with John Rudy. My gut tells me the problem is in SomeProprietarySessionManagementLookup().
.. and your consultants do not sound to sure of themselves.
Storing in Session in not async. So that isn't true unless that function is async. But even so, since it isn't calling a BeginCall and have something to call on completion, the next line of code wouldn't execute until the Session line is complete.
For the second statement, while that could be used, it isn't exactly a best practice and you have a few things to note with it. You save the cost of throwing an exception, but wouldn't you want to know that you are trying to divide by zero instead of just moving past it?
I don't think that is a solid suggestion at all.
Quite strange. On the second item it may or may not be faster. It certainly isn't the same functionality though.
Typical "consultant" bollocks:
The problem is with whatever SomeProprietarySessionManagementLookup is doing
Exceptions are only expensive if they're thrown. Don't be afraid of try..catch, but throws should only occur in exceptional circumstances. If variable y shouldn't be zero then an ArgumentOutOfRangeException would be appropriate.
I'm guessing your consultant is suggesting use a status variable instead of exception for error handling is a better practice? I don't agree. How often does people forgot or too lazy to do error checking for return values? Also, pass/fail variable is not informative. There are more things can go wrong other than divide by zero like integer x/y is too big or x is NaN. When things go wrong, status variable cannot tell you what went wrong, but exception can. Exception is for exceptional case, and divide by zero or NaN are definitely exceptional cases.
The session thing is possible. It's a bug, beyond doubt, but it could be that the write arrives at whatever custom session state provider you're using after the next read. The session state provider API accommodates locking to prevent this sort of thing, but if the implementor has just ignored all that, your consultant could be telling the truth.
The second issue is also kinda valid. It's not quite idiomatic - it's a slightly reversed version of things like int.TryParse, which are there to avoid performance issues caused by throwing lots of exceptions. But unless you're calling that code an awful lot, it's unlikely it'll make a noticeable difference (compared to say, one less database query per page etc). It's certainly not something you should do by default.
If SomeProprietarySessionManagementLookup(); is doing an asynchronous assignment it would more likely look like this:
SomeProprietarySessionManagementLookup(Session["UserID"]);
The very fact that the code is assigning the result to Session["UserID"] would suggest that it is not supposed to be asynchronous and the result should be obtained before Response.Redirect is called. If SomeProprietarySessionManagementLookup is returning before its result is calculated they have a design flaw anyway.
The throw an exception or use an out parameter is a matter of opinion and circumstance and in actual practice won't amount to a hill of beans which ever way you do it. For the performance hit of exceptions to become an issue you would need to be calling the function a huge number of times which would probably be a problem in itself.
If the consultants deployed their ASP.NET application on your server(s), then they may have deployed it in uncompiled form, which means there would be a bunch of *.cs files floating around that you could look at.
If all you can find is compiled .NET assemblies (DLLs and EXEs) of theirs, then you should still be able to decompile them into somewhat readable source code. I'll bet if you look through the code you'll find them using static variables in their proprietary lookup code. You'd then have something very concrete to show your bosses.
This entire answer stream is full of typical programmer attitudes. It reminds me of Joel's 'Things you should never do' article (rewrite from scratch.) We don't really know anything about the system, other than there's a bug, and some guy posted some code online. There are so many unknowns that it is ridiculous to say "This guy does not know what he is doing."
Rather than pile on the Consultant, you could just as easily pile on the person who procured their services. No consultant is perfect, nor is a hiring manager ... but at the end of the day the real direction you should be taking is very clear: instead of trying to find fault you should expend energy into working collaboratively to find solutions. No matter how skilled someone is at their roles and responsibilities they will certainly have deficiencies. If you determine there is a pattern of incompentencies then you may choose to transition to another resource going forward, but assigning blame has never solved a single problem in history.
On the second point, I would not use exceptions here. Exceptions are reserved for exceptional cases.
However, division of anything by zero certainly does not equal zero (in math, at least), so this would be case specific.

Categories

Resources