C# Member Variable Scope - c#
I have three/four functions in my VSTO addin and some member variables:
Member Variables:
private Dictionary<string, string> clientDict;
private Dictionary<string, string> clientHistoryDict;
Function that works with those variables:
public void generateClientDict()
{
clientDict.Add("alcatel-lucent.com", "Alcatel-Lucent");
clientDict.Add("emerson.com", "Emerson");
clientDict.Add("ericsson.com", "Ericsson");
clientDict.Add("fortress-technologies.com", "Fortress Technologies");
clientDict.Add("genesys.com", "Genesys");
clientDict.Add("hitachi.com", "Hitachi Data Systems");
clientDict.Add("hp.com", "Hewlett Packard");
clientDict.Add("lg.com", "LG Electronics");
clientDict.Add("samsung.com", "Samsung");
clientDict.Add("sap.com", "SAP");
clientDict.Add("tellabs.com", "Tellabs");
clientDict.Add("thiel-audio.com", "Thiel Audio");
clientDict.Add("xerox.com", "Xerox");
clientDict.Add("zebra.com", "Zebra Technologies");
clientHistoryDict.Add("3com.com", "3Com- CommWorks");
clientHistoryDict.Add("3m.com", "3M");
clientHistoryDict.Add("abis.com", "ABIS");
clientHistoryDict.Add("acxiom.com", "Acxiom");
clientHistoryDict.Add("ajusa.com", "AJ-USA");
clientHistoryDict.Add("akamai.com", "Akamai Technologies");
clientHistoryDict.Add("alcatel-lucent.com", "Alcatel-Lucent");
clientHistoryDict.Add("avaya.com", "Avaya");
clientHistoryDict.Add("beckmancoulter.com", "Beckman Coulter");
clientHistoryDict.Add("bellsouth.com", "BellSouth");
clientHistoryDict.Add("bridgevine.com", "Bridgevine");
clientHistoryDict.Add("casio.com", "Casio");
clientHistoryDict.Add("cca.com", "CCA");
clientHistoryDict.Add("ccs.com", "CCS");
clientHistoryDict.Add("centurylink.com", "CenturyLink");
clientHistoryDict.Add("chinatelecom.com", "China Telecom");
clientHistoryDict.Add("cisco.com", "Cisco");
clientHistoryDict.Add("comcast.com", "Comcast");
clientHistoryDict.Add("comodo.com", "Comodo");
clientHistoryDict.Add("comverge.com", "Comverge");
clientHistoryDict.Add("coriant.com", "Coriant (Spin off from Tellabs)");
clientHistoryDict.Add("daneelectric.com", "Dane Electric");
clientHistoryDict.Add("dell.com", "Dell");
clientHistoryDict.Add("disney.com", "Disney");
clientHistoryDict.Add("siemens.com", "Efficient Networks- Siemens");
clientHistoryDict.Add("emc.com", "EMC");
clientHistoryDict.Add("emergentcommunications.com", "Emergent Communications");
clientHistoryDict.Add("emerson.com", "Emerson");
clientHistoryDict.Add("epson.com", "Epson");
clientHistoryDict.Add("ericsson.com", "Ericsson");
clientHistoryDict.Add("exigen.com", "Exigen Services");
clientHistoryDict.Add("frbny.com", "Federal Reverse Bank of New York");
clientHistoryDict.Add("hometeamsports.com", "Fox Home Team Sports");
clientHistoryDict.Add("freemansoundlabs.com", "Freeman Sound Labs");
clientHistoryDict.Add("genesys.com", "Genesys");
clientHistoryDict.Add("here.com", "HERE, a Nokia Company");
clientHistoryDict.Add("hp.com", "Hewlett Packard");
clientHistoryDict.Add("hitachi.com", "Hitachi Data Systems");
clientHistoryDict.Add("intel.com", "Intel");
clientHistoryDict.Add("lg.com", "LG Electronics");
clientHistoryDict.Add("samsung.com", "Samsung");
clientHistoryDict.Add("sap.com", "SAP");
clientHistoryDict.Add("subway.com", "Subway");
clientHistoryDict.Add("tellabs.com", "Tellabs");
clientHistoryDict.Add("thiel-audio.com", "Thiel Audio");
clientHistoryDict.Add("xerox.com", "Xerox");
clientHistoryDict.Add("zebra.com", "Zebra Technologies");
}
Now this function works with the member variables. (All of these are in the same class). But these functions do not:
public void populateClientDict(SqlConnection conn)
{
//Dictionary<string, string> clientDict = new Dictionary<string, string>(); If I don't add this I get an error
try
{
using (conn)
{
SqlCommand command = new SqlCommand(
#"SELECT ClientDirName, ClientEmailDomain FROM ClientTable;",
conn);
conn.Open();
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
string clientDir = reader.GetString(0);
string clientEmail = reader.GetString(1);
clientDict.Add(clientEmail, clientDir);
}
}
else
{
MessageBox.Show("No rows found in ClientTable", "Rows Not Found", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
reader.Close();
}
}
catch (InvalidOperationException ex)
{
MessageBox.Show(String.Format("Exception while accessing ClientTable: {0}", ex), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (SqlException ex)
{
MessageBox.Show(String.Format("Exception while accessing ClientTable: {0}", ex), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
public void populateClientHistoryDict(SqlConnection conn)
{
//Dictionary<string, string> clientHistoryDict = new Dictionary<string, string>(); if I don't add this I get an error
try
{
using (conn)
{
SqlCommand command = new SqlCommand(
#"SELECT ClientDirName, ClientEmailDomain FROM ClientHistoryTable;",
conn);
conn.Open();
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
string clientDir = reader.GetString(0);
string clientEmail = reader.GetString(1);
clientHistoryDict.Add(clientEmail, clientDir);
}
}
else
{
MessageBox.Show("No rows found in ClientHistoryTable", "Rows Not Found", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
reader.Close();
}
}
catch (InvalidOperationException ex)
{
MessageBox.Show(String.Format("Exception while accessing ClientHistoryTable: {0}", ex), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (SqlException ex)
{
MessageBox.Show(String.Format("Exception while accessing ClientHistoryTable: {0}", ex), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
As I wrote in the commented out line in the functions, unless i declare the dictionaries in those functions I get this error:
I get the error on this line:
clientDict.Add(clientEmail, clientDir); in populateClientDict() and clientHistoryDict.Add(clientEmail, clientDir); in populateClientHistoryDict()
An exception of type 'System.NullReferenceException' occurred in Archive.dll but was not handled in user code
Additional information: Object reference not set to an instance of an object.
I had a feeling the error is related this part of the functions where it says:
while (reader.Read())
{
clientDir = reader.GetString(0);
string clientEmail = reader.GetString(1);
clientDict.Add(clientEmail, clientDir);
}
ID is the first column, clientDir is the second column, and clientEmail is the third. Maybe I'm using reader.GetString() incorrectly? I read somewhere I could do something like reader.GetString["ClientDirName"] (ClientDirName is the column name) but I'm not sure what the correct thing to do is.
Could this be causing the error? If so, how can I access the 2nd and 3rd columns (provided ID is the first column) properly to avoid this error.
If not, what else could cause it?
I've tried a ton of combinations, as I said it works if I move the Dictionary instantiations within the functions but I don't think that's solving the actual problem.
Any assistance is much appreciated.
I'm guessing you forgot to instantiate the clientDict member variable like you do in your function.
Since your are declaring the same variable in function and instantiating, it takes the local scope (when using without this) and it works.
You could either instantiate your private member in the constructor or during the declaration itself.
private Dictionary<string, string> clientDict=new Dictionary<string, string>();
private Dictionary<string, string> clientHistoryDict=new Dictionary<string, string>();
Please follow this link, if you want to know more about scope.
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? } } }
Exception handling quandry
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"); } }
Cannot connect to an external database in SQLCLR
I am trying to create a function that will connect to an external database and run a query. When I run my function I am getting this error: Data access is not allowed in this context. Either the context is a function or method not marked with DataAccessKind.Read or SystemDataAccessKind.Read, is a callback to obtain data from FillRow method of a Table Valued Function, or is a UDT validation method. I don't think that I am doing anything strange, but here is my code. Please let me know if you spot something odd. I really don't know what else to try. [Microsoft.SqlServer.Server.SqlFunction] public static SqlString createFile() { string theQuery = "SELECT * FROM A_TABLE;"; string theConnection = "Data Source=serverName;Initial Catalog=DatabaseBane;Persist Security Info=True;User ID=login;Password=thePassword"; SqlConnection DBConnect = new SqlConnection(theConnection); try { //My code is breaking here************************************ DBConnect.Open(); } catch (Exception e) { return "Happening in the connect: " + e.Message; } SqlDataAdapter dataAdapter = new SqlDataAdapter(theQuery, DBConnect); DataTable HRNdata = new DataTable(); dataAdapter.Fill(HRNdata); FileStream stream = new FileStream(#"C:\TestFiles\demo.xls", FileMode.OpenOrCreate); ExcelWriter writer = new ExcelWriter(stream); writer.BeginWrite(); Dictionary<string, int> noteDict = new Dictionary<string, int>(); foreach (DataRow r in HRNdata.Rows) { try { noteDict.Add(r["Note"].ToString(), 1); } catch { noteDict[r["Note"].ToString()] += 1; } } int counter = 1; foreach (KeyValuePair<string, int> pair in noteDict) { writer.WriteCell(1, counter, pair.Key); writer.WriteCell(2, counter, pair.Value); counter++; } writer.EndWrite(); stream.Close(); try { DBConnect.Close(); } catch (Exception e) { return e.Message; } return ""; }
You will need to add an annotation to your method along the lines DataAccessKind.Read.
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?
Int.TryParse not resolving specified cast is not valid error
Alright I originally started out using a Convert.ToInt32(myradTextBox.Text) then it said specified cast is not valid. I did some research on here and decided to try Int.TryParse. Upon doing so I still received this error. What I am trying to do is when the user enters an ID and hits the create button, it searches the DB to see if that ID is already there. I have also tried to convert the bool value from my Int.TryParse to int using Convert.ToInt32(Result) still same error (see below in third code post for where that would be posted). Maybe it has something to do with my comparison method. Below I have provided the Int.TryParse method with values. The Method I am calling to check the userinput is not in the db currently and my if statement that is catching the statement. Any input on how to fix this would be greatly appreciated. I am still new to most of this stuff so I apologize if leaving any critical info off. Just ask if you need clarification or something elaborated. Here is my method for comparison: public bool isValidID(int id) { SqlConnection dbConn = null; int count = 0; try { using (dbConn = new SqlConnection(Properties.Settings.Default["tville"].ToString())) { string sql = "SELECT Count(*) FROM PackLabelFormat where PackFormatID = #PackFormatID"; SqlCommand cmd = dbConn.CreateCommand(); cmd.CommandText = sql; cmd.Parameters.AddWithValue("#PackFormatID", id); dbConn.Open(); using (SqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); count = reader.GetInt16(0); } } } catch (Exception ex) { throw ex; } if (count > 0) return false; return true; } Here is my variables that I use in my Int.TryParse method: string IDselect = rTxtBoxFormatID.Text.ToString(); int resultInt; bool result = int.TryParse(IDselect, out resultInt); Lastly here is my method that is catching the error: SqlConnection dbConn = null; LabelData labelList = new LabelData(); try { using (dbConn = new SqlConnection(Properties.Settings.Default["tville"].ToString())) { if (SelectedVersion.isValidID(resultInt)) { SelectedVersion.PackFormatID = resultInt; } else { MessageBox.Show("ID already in use!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } catch (Exception ex) { throw ex; }
The database column did not support Int16 aka short. Which was why my specified cast is not valid error never went away no matter what I tried. Thank you for your help in this matter! Here is the code to further illustrate what the problem was. using (SqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); //count = reader.GetInt16(0); needs to be reader.GetInt32(0); }