Throwing exceptions problem

J

J055

Hi

I understand that a throw statement throws an exception immediately and
unconditionally. Control never reaches the statement immediately following
the throw. The following method seems to stop the statements (if
Enum.IsDefined is false) after the throw and return null to the calling
proceedure. Then the calling proc raises a NullReferenceException. Basically
it looks to me like the throw statement is not stopping the programme
immediately. Can this be true or have I missed something?


public int AddAccount(...byte accountType...)
{
// Check that a valid account type exists as an AccountType Enum
if (!Enum.IsDefined(typeof(AccountTypes), accountType))
throw new ArgumentOutOfRangeException("AccountType must have a matching
Enum.");

....
// do some db inserting


// Add the new account
return account.AccountID;
}

Many thanks
Andrew
 
B

Barry Kelly

J055 said:
I understand that a throw statement throws an exception immediately and
unconditionally. Control never reaches the statement immediately following
the throw.
Yes.

The following method seems to stop the statements (if
Enum.IsDefined is false) after the throw and return null

That is not possible, since the method returns an 'int' value, which
cannot be null.
to the calling
proceedure. Then the calling proc raises a NullReferenceException. Basically
it looks to me like the throw statement is not stopping the programme
immediately. Can this be true or have I missed something?
public int AddAccount(...byte accountType...)
{

The code looks like it should either throw an exception or return the
value of account.AccountID - if you're getting a NullReferenceException
it might be because 'account' is null. It's not possible to tell much
more without more information or more complete code.

-- Barry
 
J

J055

Hi Barry

This is the complete method. My Enums don't contain a 0 value so if I send
in an accountType of 0 my ArgumentOutOfRangeException should be raised. I
know that if I remove the throw statements from the method then it always
return an integer. So I don't understand why it should return null if the
ArgumentOutOfRangeException is raised.

Thanks
Andrew

public int AddAccount(string code,

string email,

string password,

string friendlyName,

string firstName,

string lastName,

byte accountType,

bool isActive,

byte role

)

{

// Check that a valid account type exists as an AccountType Enum

if (!Enum.IsDefined(typeof(AccountTypes), accountType))

throw new ArgumentOutOfRangeException("AccountType must have a matching
Enum.");

// Check that a valid role exists in the AccountRoles Enum

if (!Enum.IsDefined(typeof(AccountRoles), role))

throw new ArgumentOutOfRangeException("Role must have a matching
AccountRoles Enum.");


// Create a new AccountsRow instance

ScsDataSet.AccountsDataTable accounts = new ScsDataSet.AccountsDataTable();

ScsDataSet.AccountsRow account = accounts.NewAccountsRow();

account.Code = code;

account.Email = email;

account.Password = password;

account.FriendlyName = friendlyName;

account.FirstName = firstName;

account.LastName = lastName;

account.AccountType = accountType;

account.IsActive = isActive;

account.Role = role;

// Add the new account

accounts.AddAccountsRow(account);

int rowsAffected = Adapter.Update(accounts);


return account.AccountID;

}
 
J

J055

Hi again

Don't know if this helps. The ObjectDataSource.InsertMethod is set to the
AddAccount method. I then have the Inserted event handle the returned
integer. This is where I get a NullReferenceException becuase the
e.ReturnValue is a null object. Why does the application not stop at my
thrown exception? It seems to get lost, i.e. no stack trace information or
innerexception seems to be available.

protected void odsAccount_Inserted(object sender,
ObjectDataSourceStatusEventArgs e)
{
Trace.Warn(e.Exception.Message);
// writes out: Exception has been thrown by the target of an invocation.

// add the new AccountID to the Select Parameters
odsAccount.SelectParameters.Add("AccountID", TypeCode.Int32,
e.ReturnValue.ToString());
}
 
B

Barry Kelly

J055 said:
This is the complete method. My Enums don't contain a 0 value so if I send
in an accountType of 0 my ArgumentOutOfRangeException should be raised. I
know that if I remove the throw statements from the method then it always
return an integer. So I don't understand why it should return null if the
ArgumentOutOfRangeException is raised.

It *cannot* return a null, because you cannot convert a null value into
a plain integer type ('int'). Put a breakpoint in the code that calls
the method where it receives the return value - or better yet, tell us
where exactly the exception is caused (i.e. enable 'break on exception'
for the appropriate exception if it isn't already, in Debug | Exceptions
menu).

-- Barry
 
J

Jon Skeet [C# MVP]

J055 said:
This is the complete method. My Enums don't contain a 0 value so if I send
in an accountType of 0 my ArgumentOutOfRangeException should be raised. I
know that if I remove the throw statements from the method then it always
return an integer. So I don't understand why it should return null if the
ArgumentOutOfRangeException is raised.

Rather than give a complete method, please give a short but complete
program.

See http://www.pobox.com/~skeet/csharp/complete.html for more on what I
mean by that.
 
J

Jeffrey Tan[MSFT]

Hi J055,

Since you provided 2 separate code snippets of your project, it is hard for
the community to image the relationship between them, so it is almost
impossible for us to judge if your second reply has anything to do with
first AddAccount() method issue.

Let's focus on your first AddAccount() exception issue first.

To find out why the AddAccount() will return a null reference to the
calling procedure, the simplest way is placing a breakpoint in the
AddAccount() method and run your code under debugger. Then you can use F10
to step through each statement in this method, it should be easy to find
out which statement finally caused the method to exit and why null
reference is returned.

Based on my experience, I suspect the ArgumentOutOfRangeException is not
thrown. Because if the ArgumentOutOfRangeException is thrown, the
AddAccount() method will terminate execution immediately and it will not
return anything to the calling procedure.

Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
W

Walter Wang [MSFT]

Hi Andrew,

I understand that this post is related to your another post "Change
FormView.ChangeMode to Edit after Insert" in
microsoft.public.dotnet.framework.aspnet.

If the insert method of ObjectDataSource throws exception, it will be
catched and stored in the Inserted event's parameter
ObjectDataSourceStatusEventArgs.Exception property:

#ObjectDataSourceStatusEventArgs.Exception Property
http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.objectdat
asourcestatuseventargs.exception.aspx

You need to check for the Exception property before reading the ReturnValue:

protected void odsAccount_Inserted(object sender,
ObjectDataSourceStatusEventArgs e)
{
if (e.Exception != null) {
Trace.Warn(e.Exception.Message);
// writes out: Exception has been thrown by the target of an
invocation.
} else {
// add the new AccountID to the Select Parameters
odsAccount.SelectParameters.Add("AccountID", TypeCode.Int32,
e.ReturnValue.ToString());
}
}

Hope this helps. Please feel free to post here if anything is unclear.

By the way, you don't have to open a new post for this. Since it's related
to your another post, posting there will make others to understand your
question more easier.



Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
W

Walter Wang [MSFT]

I forgot to mention that you need to use e.Exception.InnerException to find
the real exception that thrown in the insert method. So you actually want
to log the message using:

Trace.Warn(e.Exception.InnerException.Message);


Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
J

J055

Hi

Thanks for all the advise. Apologies for the confusing posts. I think I have
a clearer picture of what's been happing so I'll try to outline it here:

I'm using ObjectDataSource Insert to call my AddAccount business object. I
want to check some values and throw an exception if they are not expected.
Basically I wasn't seeing the exception because I wasn't handling it in the
web application (Is that what I mean?). I modified the ObjectDataSource
Inserted method as Walter suggested. Now I can see the error.

protected void odsAccount_Inserted(object sender,
ObjectDataSourceStatusEventArgs e)
{
if (e.Exception != null)
{
Trace.Warn(e.Exception.InnerException.Message);
// displays: System.ArgumentOutOfRangeException
}
else
{
// add the new AccountID to the Select Parameters
int accountID = (int)e.ReturnValue;
odsAccount.SelectParameters.Add("AccountID", TypeCode.Int32,
accountID.ToString());
}
}

I need to brush up on handling exceptions, bubbling etc. As I don't expect
to receive the ArgumentOutOfRangeException exception in my working
application (I will use validation controls) should I throw the exception
again in the odsAccount_Inserted method?

Many thanks
Andrew
 
W

Walter Wang [MSFT]

Hi Andrew,

I think it should be ok to throw e.Exception.InnerException in the Inserted
event. However, depends on your application's actual implementation on
exception handling, you need to test if it works correctly. Pleaes feel
free to post your result here.


Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 

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