Exception handling quandry - c#

I am throwing a new exception when a database row is not found.
Class that was called:
public ProfileBO retrieveProfileByCode(string profileCode)
{
return retrieveSingleProfile("profile_code", profileCode);
}
private ProfileBO retrieveSingleProfile(string termField, string termValue)
{
ProfileBO profile = new ProfileBO();
//Query string is temporary. Will make this a stored procedure.
string queryString = " SELECT * FROM GamePresenterDB.gp.Profile WHERE " + termField + " = '" + termValue + "'";
using (SqlConnection connection = new SqlConnection(App.getConnectionString()))
{
connection.Open();
SqlCommand command = new SqlCommand(queryString, connection);
SqlDataReader reader = command.ExecuteReader();
if (reader.Read())
{
profile = castDataReadertoProfileBO(reader, profile);
}
else
{
// No record was selected. log it and throw the exception (We'll log it later, for now just write to console.)
Console.WriteLine("No record was selected from the database for method retrieveSingleProfile()");
throw new InvalidOperationException("An exception occured. No data was found while trying to retrienve a single profile.");
}
reader.Close();
}
return profile;
}
However, when I catch the exception in the calling class, 'e' is now null. What am I doing wrong? I believe this works fine in Java, so C# must handle this differently.
Calling class:
private void loadActiveProfile()
{
try
{
ProfileBO profile = profileDAO.retrieveProfileByCode(p.activeProfileCode);
txtActiveProfileName.Text = profile.profile_name;
}
catch (InvalidOperationException e)
{
}
}

Now all the code has been put in the question, you can move the try catch outside of your 'loadActiveProfile' method and place it into 'retrieveSingleProfile'.
private void loadActiveProfile()
{
ProfileBO profile = profileDAO.retrieveProfileByCode(p.activeProfileCode);
txtActiveProfileName.Text = profile.profile_name;
}
removed the try catch^
private ProfileBO retrieveSingleProfile(string termField, string termValue)
{
try {
ProfileBO profile = new ProfileBO();
//Query string is temporary. Will make this a stored procedure.
string queryString = " SELECT * FROM GamePresenterDB.gp.Profile WHERE " + termField + " = '" + termValue + "'";
using (SqlConnection connection = new SqlConnection(App.getConnectionString()))
{
connection.Open();
SqlCommand command = new SqlCommand(queryString, connection);
SqlDataReader reader = command.ExecuteReader();
if (reader.Read())
{
profile = castDataReadertoProfileBO(reader, profile);
}
else
{
// No record was selected. log it and throw the exception (We'll log it later, for now just write to console.)
Console.WriteLine("No record was selected from the database for method retrieveSingleProfile()");
throw new InvalidOperationException("An exception occured. No data was found while trying to retrienve a single profile.");
}
reader.Close();
}
return profile;
}
catch(InvalidOperationException e)
{
}
}
Added try catch in the correct place.

You need to step into the catch block for e to be set to the thrown InvalidOperationException:
catch (System.InvalidOperationException e)
{
int breakPoint = 0; //<- set a breakpoint here.
//Either you reach the breakpoint and have an InvalidOperationException, or you don't reach the breakpoint.
MessageBox.Show(e.Message);
}
Also make sure that the InvalidOperationException you throw is actually a System.InvalidOperationException and not some custom type of yours called "InvalidOperationException".

Like #Clemens said, you need to show all the relevant code.
As a quick test, this works just fine:
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("Throwing error");
ThrowException();
}
catch (InvalidOperationException e)
{
Console.WriteLine(e.Message);
}
Console.ReadKey(true);
}
static void ThrowException()
{
throw new InvalidOperationException("Blah blah blah");
}
}

Related

How to store result from mysql query

How do I store the results from a mysql query for use in other classes most efficiently?
I've tried the following code, which executes properly and stores all data in reader as it should. Reading the DataReader here works fine if I want to!
public class DatabaseHandler
{
public void MySqlGetUserByName(string input_username, MySqlDataReader reader)
{
try
{
_database.Open();
string query = "SELECT * FROM users WHERE username = '#input'";
MySqlParameter param = new MySqlParameter(); param.ParameterName = "#input"; param.Value = input_username;
MySqlCommand command = new MySqlCommand(query, _database);
command.Parameters.Add(param);
reader = command.ExecuteReader();
_database.Close();
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
But when I try to read the same DataReader here, it is null and throws an exception (right after Debug6).
public class LoginHandler
{
public static void UserAuth(Client user, string input_username, string input_password)
{
DatabaseHandler dataBase = new DatabaseHandler();
MySqlDataReader dataReader = null;
dataBase.MySqlGetUserByName(input_username, dataReader);
Console.WriteLine("Debug6");
if (!dataReader.HasRows)
{
user.SendChatMessage("No match found.");
return;
}
while (dataReader.Read())
{
user.SetData("ID", (int)dataReader[0]);
user.SetData("username", (string)dataReader[1]);
user.SetData("email", (string)dataReader[2]);
user.SetData("password", (string)dataReader[3]);
}
dataReader.Close();
}
}
Please let me know how to make this work, or if there is a more efficient way of doing this without limiting the function of MySqlGetUserByName. The purpose of it is to input a name and a place to store all info from the match in the database.
Also, feel free to drop in any other suggestions that could make the code more efficient.
You could change your MySqlGetUserByName to return a User instance if all goes well, otherwise you return a null instance to the caller (Or you can thrown an exception, or you can set a global error flag in the DatabaseHandler class..., but to keep things simple I choose to return a null)
public class DatabaseHandler
{
public User MySqlGetUserByName(string input_username)
{
User result = null;
try
{
string query = "SELECT * FROM users WHERE username = #input";
using(MySqlConnection cnn = new MySqlConnection(......))
using(MySqlCommand command = new MySqlCommand(query, cnn))
{
cnn.Open();
command.Parameters.AddWithValue("#input", input_username);
using(MySqlDataReader dataReader = command.ExecuteReader())
{
if (dataReader.Read())
{
result = new User();
result.ID = Convert.ToInt32(dataReader[0]);
..... and so on with the other user properties ....
}
}
}
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
// Return the user to the caller. If we have not found the user we return null
return result;
}
}
In the same way the caller handles the situation
public class LoginHandler
{
public static void UserAuth(string input_username, string input_password)
{
DatabaseHandler dataBase = new DatabaseHandler();
User result = dataBase.MySqlGetUserByName(input_username);
// If we have not found the user we have a null in the variable
if(result == null)
{
// Send your message using a static method in the user class
// User.SendMessage("User with username {input_username} not found!");
}
else
{
// User ok. return it? or do something with its data?
}
}
}

Connection exception from SqlCeDataAdapter.fill()

Following numerous examples here and on MSDN, I can't figure out why I'm encountering an exception on adapter.Fill() below, nor do I understand why the exception is not caught here in the try{...} catch() clock, but rather in Program.Main().
The exception is
"- $exception {"Exception has been thrown by the target of an invocation."} System.Exception {System.Reflection.TargetInvocationException}
and the inner exception is
_message "ExecuteScalar: Connection property has not been initialized." string
What on earth am I missing here? Connection not initialized? I just opened it!
private static SqlCeConnection _cnxn = null;
public static SqlCeConnection cnxn
{
get
{
if (_cnxn == null)
{
_cnxn = new SqlCeConnection(global::Format_Generator_15.Properties.Settings.Default.FGConnectionString);
}
return _cnxn;
}
}
private static DataTable inputTable = null;
public static DataTable InputTable
{
get
{
if (inputTable == null)
{
if (cnxn.State == ConnectionState.Closed)
cnxn.Open();
try
{
SqlCeDataAdapter adapter = new SqlCeDataAdapter("select * from input", cnxn);
inputTable = new DataTable();
adapter.Fill(inputTable);
}
catch (Exception ex)
{
Console.WriteLine("Couldn't get the input table. " + ex.Message);
}
}
return inputTable;
}
}

Transactionscope rollback

I have a method inside a main one. I need the child method to be able to roll back if the parent method fails. The two data connections use different servers . Before I added the transaction scopes, they worked well. But when I tie them together, the child method aborts.
Edit: Error message: Network access for distributed transaction Manager(MSDTC) has been disabled. Please enable DTC for network access in the security configuration for MSDTC using Component Service Administrative tool.
public static void LoopStudent()
{
try
{
using(TransactionScope scope = new TransactionScope())
{
String connString = ConfigurationManager.AppSettings["DBConnection"];
using(SqlConnection webConn = new SqlConnection(connString))
{
webConn.Open();
String sql = "select * from students";
using(SqlCommand webComm = new SqlCommand(sql, webConn))
{
using(SqlDataReader webReader = webComm.ExecuteReader())
{
if (webReader.HasRows)
{
while (webReader.Read())
{
int i = GetNextId();
}
}
else
Console.WriteLine("wrong");
}
}
}
scope.Complete();
}
}
catch (Exception ex)
{
Console.WriteLine("Error " + ex.Message);
}
} //End LoopThroughCart
public static int GetNextId(String str)
{
int nextId = 0;
String connString = ConfigurationManager.AppSettings["SecondDBConnection"];
try
{
using(TransactionScope scope = new TransactionScope())
{
using(SqlConnection webConn = new SqlConnection(connString))
{
webConn.Open();
using(SqlCommand webComm = new SqlCommand("GetNextId", webConn))
{
//do things
}
}
scope.Complete();
}
}
catch (TransactionAbortedException ex)
{
Console.WriteLine("TransactionAbortedException Message: {0}", ex.Message);
}
catch (ApplicationException ex)
{
Console.WriteLine("ApplicationException Message: {0}", ex.Message);
}
return nextId;
} //End GetNextId
If you do not use RequireNew in you inner method, the inner method will be automatically rolled back if the parent fails to commit the transaction.
What error are you getting?

Write & Read App Config Setting

I have an application that need to check to the database if a particular code exists; if it does exist, then have to load the corresponding value of that code else return null.
I don't want to hit the database for each code(running about 200.000 codes ).
so i got this small app to test the app.conf
public static void setAppSetting(string key, string value)
{
Configuration config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
if (config.AppSettings.Settings != null)
{
config.AppSettings.Settings.Remove(key);
}
config.AppSettings.Settings.Add(key, value);
config.Save(ConfigurationSaveMode.Modified);
}
public static string getAppSetting(string key)
{
try
{
Configuration config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
return config.AppSettings.Settings[key].ToString();
}
catch (Exception ex)
{
throw ex;
}
}
private static void loadKeysValues()
{
using (SqlConnection Gcon = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["constr"].ConnectionString))
{
//Open Connection
Gcon.Open();
using (SqlCommand sqlCmd = new SqlCommand("SELECT key,value FROM tables", Gcon))
{
using (SqlDataReader reader = sqlCmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
System.Console.WriteLine(reader.GetString(0) + " , " + reader.GetString(1));
setAppSetting(reader.GetString(0), reader.GetString(1));
}
}
} // End of SqlDataReader
} // end of SqlCommand
}
}
static void Main(string[] args)
{
System.Console.WriteLine("Loading.........");
loadKeysValues();
System.Console.WriteLine("Completed");
System.Console.WriteLine("Input a key to get its value");
var input = System.Console.Read().ToString();
System.Console.WriteLine(getAppSetting(input));
System.Console.ReadLine();
}
But I got an error with the getAppSetting() at this line:
return config.AppSettings.Settings[key].ToString();
Error: Object reference not set to an instance of an object.
Plz help
Make sure that the value isn't null.
Try this:
if (config.AppSettings.Settings.ContainsKey(key) &&
config.AppSettings.Settings[key] != null)
{
return config.AppSettings.Settings[key].ToString();
}
Most likely you're trying to access a setting that doesn't exist. You could handle that exception in your catch block and return null in that case.
ToString() method donĀ“t return the value, try with Value property:
return config.AppSettings.Settings[key].Value;

How to move to next row in datatable if one row catches an error? C# 2.0

I am getting data from a mySql database and I am inserting it into another system. If a column has data in an incorrect format I log this and go to next row in the datatable. It works as expected but now if I have a search function in my method that gets some additional data and this function fails I want to immediately log this and go to next row. As it is now I just log it but it still gets inserted (without the value that didn't meet the search criteria).
My code:
private void updateCustomer()
{
MySqlConnection connection = new MySqlConnection("server=myServer;database=myDatabase;uid=myID;password=myPass");
MySqlCommand command = new MySqlCommand(#"mySelectCommand", connection);
DataTable customerTbl = new DataTable();
MySqlDataReader reader;
try
{
connection.Open();
reader = command.ExecuteReader();
if (reader.HasRows)
{
customerTbl.Load(reader);
}
reader.Close();
}
catch (Exception ex)
{
_out.error("Could not connect to mySql database");
}
finally
{
connection.Close();
}
foreach (DataRow row in customerTbl.Rows)
{
// Declare the customer variables
string customerID = Encoding.ASCII.GetString((byte[])row["Customer ID"]);
string ChildOf = row["Child of"].ToString();
// Create the customer object
Customer customer = new Customer();
customer.entityId = customerID;
if (ChildOf != "")
{
RecordRef parentRef = new RecordRef();
try
{
parentRef.internalId = searchCustomer(ChildOf);
}
catch
{
// If it fails here I want to log the customerID and then go to the next row in the datatable (could not find the internalid for ChildOf
_out.error(customerID + " was not updated. Error: invalid format Parent string");
}
finally
{
parentRef.typeSpecified = false;
customer.parent = parentRef;
}
}
// Invoke update() operation
WriteResponse response = _service.update(customer);
// Process the response
if (response.status.isSuccess)
{
}
else
{
_out.error(customerID + " was not updated. Error: " + getStatusDetails(response.status));
}
}
}
You need to remove the row in the catch block, and change the foreach loop to a backwards for loop to handle the removals.
I realized that I want to log the other failed fields as well. Maybe it's an inefficient way but I did something like:
bool findParent = true;
if (ChildOf != "")
{
try
{
RecordRef parentRef = new RecordRef();
parentRef.internalId = searchCustomer(ChildOf);
parentRef.typeSpecified = false;
customer.parent = parentRef;
}
catch
{
findParent = false;
_out.error(customerID + " was not inserted. Error: invalid format Parent string");
}
}
And then an if statement before trying to insert:
if (findPartner == true && findParent == true)
{
response = _service.add(customer);
// Process the response
if (response.status.isSuccess)
{
}
else
{
_out.error(customerID + " was not inserted. Error: " + getStatusDetails(response.status));
}
}
else
{
//_out.error(customerID + " was not updated. Error: " + getStatusDetails(response.status));
}
Use the row.HasError property.

Categories

Resources