Cannot implicity convert "void" to "bool" - c#

Can anyone point to me what is wrong with the code I have? The first function is on a different aspx file than the second function.
protected void btnManageUsersAddUser_Click(object sender, EventArgs e)
{
if (clsDataLayer.SaveUser(Server.MapPath("PayrollSystem_DB.mdb"), txtManageUsersName.Text, txtManageUsersPassword.Text, ddlSecurityLevel.SelectedValue))
{
lblAddUserMsg.Text = "The user was successfully added";
grdManagePersonnel.DataBind();
}
else
{
lblAddUserMsg.Text = "The user was not successfully added";
}
The following function has originally "bool" instead of "void" but my professor told me to change it to "void" due to error of not all returns a value.
public static void SaveUser(string Database, string UserName, string UserPassword, string SecurityLevel)
{
bool recordSaved;
try
{
// Create connection
OleDbConnection conn = new OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=" + Database);
conn.Open();
OleDbCommand command = conn.CreateCommand();
string strSQL;
// Insert to tblUserLogin
strSQL = "Insert into tblUserLogin " +
"(UserName, UserPassword, SecurityLevel) values ('" +
UserName + "', '" + UserPassword + "', '" + SecurityLevel + "')";
// Process data
command.CommandType = CommandType.Text;
command.CommandText = strSQL;
// Add your comments here
command.ExecuteNonQuery();
// Closes the transaction when true
conn.Close();
recordSaved = true;
}
catch (Exception ex)
{
}
}

Since you have changed the method return type to type void, you can no longer use it in the conditional statement you have here:
if (clsDataLayer.SaveUser(Server.MapPath("PayrollSystem_DB.mdb"),
txtManageUsersName.Text, txtManageUsersPassword.Text, ddlSecurityLevel.SelectedValue))
...the conditional expects the expression to be reduced to a boolean value.
Your professor might have had a point that not all paths returned a value in a previous edition of your code. You will need to make sure that all paths return a true or false value if your method returns a boolean. For example, you could modify your code to return a boolean value again and return the following values:
...
return true;
}
catch (Exception ex)
{
return false;
}
...
Note that I have removed the "recordSaved" variable as it was unnecessary; if you are only going to use it in that one spot I would suggest returning the true/false values themselves.

Yes, you changed it to return nothing but then you still expect it to return something because you're still trying to use the result:
if (clsDataLayer.SaveUser( ...
Either change that expectation (losing the ability to return valuable information to the caller), or go back to your original version and ensure all code paths return a value.
Your professor's advice is akin to:
You: My car has a flat tire.
Prof: Well, take the tire off.
You: Er, now my car still won't go.
While the professor's advice to remove the flat tire has indeed fixed the immediate problem (inasmuch as your car no longer has a flat tire), it's not really an adequate solution. Changing things without understanding the root cause (a) of the problem frequently leads to situations like that you currently find yourself in.
Your professor should have advised you to understand why you were getting the error and fix that, rather than opting for a quick fix with ramifications elsewhere.
(a) The root cause of this problem is not that your value returns a boolean value, it's because there's a mismatch between what the caller expects and what the callee delivers.

I disagree with your professors recommendation. Changing the return type of your method to void because all paths do not return a value is like slapping a bandage on an infected cut and expecting it to heal.
A better solution, IMO, would be to ensure that all paths do return a value (either true or false).
For example, in your method, change:
bool recordSaved;
to:
bool recordSaved = false;
Then, if at the end of your try section (before the catch line), add:
recordSaved = true;
Then return recordSaved before exiting the method:
return recordSaved;
With these changes, your method will set the recordSaved value to false; it only gets set to true if the record is saved. Then you can return the value, and use the method in your if check.
The complete code would look something like this:
public static bool SaveUser(string Database, string UserName, string UserPassword, string SecurityLevel)
{
bool recordSaved = false;
try
{
// do your save
recordSaved = true;
}
catch (Exception ex)
{
// Handle the exception (logging, etc)
}
return recordSaved;
}

Related

SqlDataReader returns "Enumeration yielded no results" despite entering DataReader.Read() code block

I have a class function where I'm trying to read data from a database table using the SqlDataReader. When the SqlCmd.ExecuteReader() is called, I see(upon debugging) that the resultView of the SqlDataReader says "Enumeration yielded no results". However, the SqlDataReader.Read() still returns true and therefore enters the while() code block.
The query executes correctly on SQL, and even changing the query to get data from other tables give the same results. Please note that I have several other functions in a separate class executing the similar code to get data from these same database tables and they work without any issue.
Another observation is that after the ExecuteReader() is called, the VisibleFieldCount field of the SQLDataReader has the value = 11, which is equal to the total number of columns in the Customer table. This suggests that the reader is able read atleast some of the data from the database.
Any suggestions or help will be appreciated. Please let me know if any more information is required.
I have tried simplifying the function code as much as possible by removing any code logic other than the data retrieval part for the ease of debugging.
public bool MatchPassword(string username, string enteredPassword)
{
bool loginSuccessful = false;
string returnedpasswordbinary;
DatabaseConnection databaseConnectionObj = new DatabaseConnection();
databaseConnectionObj.CreateDBConnection(); //Sets the connection string and opens database connection
string query = "SELECT * FROM dbo.Customers WHERE CustomerID='ALFKI';";
SqlCommand sqlCommandObj = new SqlCommand();
sqlCommandObj.CommandText = query;
sqlCommandObj.Connection = databaseConnectionObj.SqlConnectionObj1;
try
{
SqlDataReader sqlDataReaderObj = sqlCommandObj.ExecuteReader();
if (sqlDataReaderObj.HasRows)
{
while (sqlDataReaderObj.Read())
{
returnedPasswordBinary = sqlDataReaderObj[0].ToString();
}
}
}
catch (Exception ex)
{
throw ex;
}
return loginSuccessful;
}
Can you please set commandtype
command.CommandType = CommandType.Text;

The Name 'data' does not exist in the current context

I am trying to generate a try catch method in a class, But I am facing this error message, Please help me to solve this.
My class is
public string Countryadd(string country, string id)
{
try
{
string data="0";
string qry1 = "select Country from Country where Country='" + country + "'";//Checking weather txtcountry(Country Name) value is already exixst or not. If exist return 1 and not exists go to else condition
SqlDataReader dr = conn.query(qry1);
if (dr.Read())
{
return data = "1";
}
else//If Country Name Not Exists
{
string qry = "insert into Country values('" + id + "','" + country + "')";//Insertin data into database Table Country
conn.nonquery(qry);
}
}
catch (Exception Ex)
{
ShowPopUpMsg(Ex.Message);
}
return data;
}
You need to put the definition of data before the try block:
string data="0";
try {
The {} brackets define the scope of a variable.
You can only access a variable within that scope.
Since you define your data variable in try block, it doesn't seems outside of this blocks. It is only available in try block and any child scope.
You can move it's definition outside of your try-catch block.
string data="0";
try
{
...
}
catch (Exception Ex)
{
ShowPopUpMsg(Ex.Message);
}
return data;
Read: 3.7 Scopes (C#) from MSDN
All variables created between the { } symbols are inside the scope of the symbols themselves.
If you need to use data outside of it, declare it before the try.
string data = string.Empty; // or initialize the value to "0" if that's the default you want.
try
{
// Don't declare data here or it won't be visible outside the try block.
// You can set the "0" or whatever value you want here though.
...
}
catch (Exception Ex)
{
...
}
return data;
data is currently defined within the scope of the try block, you need to move it outside
string data = "0";
try
{
...
}
catch(NullReferenceException ex)
{
}
catch(SomethingRelatedToDataReaderException ex)
{
}
return data;
Also, you shouldn't really try to catch Exception, you should try to catch the specific types of exceptions. This helps to avoid covering up issues as well as giving you more control
The scoping of your variable data is only inside the Try/Catch block because you defined in it.
Try to define the variable data outsiude the block.

Parameterized Update

I am trying to update a record in an access file (.accdb). I am trying to use the .net OleDbCommand and OleDbParameters. I am also trying to use a generic model and store all of the commands and parameters in the System.Data.Common abstract equivalents so that I can easily switch over to SQL Server (which I do plan to do)
So here is the actual command being used
EDIT 2/2/2013 - 9:10pm
the command.ExecuteNonQuery is inside the method named ExecuteNonQuery()
the connectionString and command are defined in the DataAccess class constructor
public class DataAccess
{
private string connectionString;
private DbConnection connection;
private DbCommand command;
private DbDataReader reader;
private DataTable data;
public DataAccess()
{
connectionString = ConfigurationSettings.AppSettings["ConnectionString"];
switch (ConfigurationSettings.AppSettings["DataBaseType"])
{
case "oledb":
connection = new OleDbConnection(connectionString);
command = new OleDbCommand(string.Empty, (OleDbConnection)connection);
break;
case "SQL":
connection = new SqlConnection(connectionString);
command = new SqlCommand(string.Empty, (SqlConnection)connection);
break;
default:
break;
}
}
public void ExecuteNonQuery(string SQL, params DbParameter[] parameters)
{
command.CommandType = CommandType.Text;
command.CommandText = SQL;
command.Parameters.AddRange(parameters);
try
{
command.Connection.Open();
try
{
command.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
finally
{
command.Connection.Close();
}
}
catch (Exception ex)
{
throw ex;
}
}
public DbParameter NewParameter(string name, object value)
{
DbParameter param;
switch (ConfigurationSettings.AppSettings["DataBaseType"])
{
case "oledb":
param = new OleDbParameter(name, value);
break;
case "SQL":
param = new SqlParameter(name, value);
break;
default:
param = null;
break;
}
return param;
}
These are the properties in the App.Config File
<add key="DataBaseType" value="oledb"/>
<add key="ConnectionString" value="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=data.accdb"/>
Now the problem is when using parameters in an update statement, the update never happens and also never throws an error. Here is the code for it.
EDIT 2/2/2013 - 9:10pm
the function DataAccess.NewParameter is in the first code block
DALayer.ExecuteNonQuery("UPDATE TileTypes SET Title = #Title, Picture = #Picture, Color = #Color WHERE ID = #ID",
DALayer.NewParameter("#Title", titleTextBox.Text.Trim()),
DALayer.NewParameter("#Picture", typePictureBox.ImageLocation),
DALayer.NewParameter("#Color", colorButton.BackColor.ToArgb()),
DALayer.NewParameter("#ID", id));
I have copied the query into access and replaced all of the parameter names with the actual data being passed, this works fine. I have tried replacing all of the parameters in the SQL text to the ? character to no effect. I have tried enclosing all of the table and column names in brackets [] also to no effect.
ID is an AutoNumber field
Title is a Text field
Picture is a Text field
Color is a Long Integer field
This is some example data that was copied directly from the parameters in the watch window for Visual Studio:
"Edit" (title)
-1 (color)
"data\images\Edit_000000.jpg" (picture)
740 (id)
That ID does exist in the database and was unchanged after the query executed.
EDIT 2/2/2013 - 9:10pm
I am not sure how to check which database is actually being updated, the only thing I could think of was that using the same connection string and connection object I did an insert statement with the same ExecuteNonquery method and it worked in the database I was viewing. And the update statement works just fine like this (without parameters):
DALayer.ExecuteNonQuery("UPDATE TileTypes SET Title = '" + titleTextBox.Text +
"', Color = " + colorButton.BackColor.ToArgb() + ", Picture = '" +
imageLocation + "' WHERE ID = " + id);
EDIT 2/2/2013 - 9:41pm
I have used everything.exe to search my computer for all of the data.accdb files on my computer, I have found no actual .accdb files besides the original but I did find these .lnk files, I do not believe they could have altered this process but I will mention it anyway
data.accdb.LNK
What you are trying to do is something I too have done in the past, but allowed to connect to OleDB (such as Access, Visual FoxPro, etc), SQL-Server, SyBase SQLAnywhere and maybe my implementation might help you. First, each of the elements you would use for connecting work on a common interface, such as IDbConnection, IDbCommand, IDbParameter, etc.
The following I'm posting is a small segment of how I originally structured such multi-database connection type. I've stripped a bunch out and not actually tested this stripped version, but it SHOULD be a good baseline for you to run with.
The premise is a baseline "MyConnection" to almost be like an abstract, but has properties and some "common" methods that would exist under EITHER subclassed definition. From this, each of the functions and parameter types are based on the "I"nterface, not a specific. However, each of the derived will create its OWN proper type. This removes the need to "Case" everything. Hope this helps you along with your Data Access Layer development.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
// for OleDB (Access, VFP, etc)
using System.Data.OleDb;
// for SQL-Server
using System.Data.SqlClient;
namespace DataMgmt
{
public class MyConnection
{
// no matter the connection to server, it will require some "handle"
// that is of type "IDbConnection"
protected IDbConnection sqlConnectionHandle;
// when querying, ANY query could have an exception that needs to have
// possible further review for handling
public Exception LastException
{ get; protected set; }
// When calling an execute command (select, insert, update, delete),
// they all can return how many rows affected
public int RowsAffectedByQuery
{ get; protected set; }
// different databases could have different connection strings. Make
// virtual and throw exception so sub-classed must return proper formatted.
public virtual string GetConnectionString()
{ throw new Exception("GetConnectionString() method must be overridden."); }
// each has its own "IDbConnection" type too
protected virtual IDbConnection SQLConnectionHandle()
{ return sqlConnectionHandle; }
public virtual IDbCommand GetSQLDbCommand()
{ throw new Exception("GetSQLDbCommand() method must be overridden."); }
// generic routine to get a data parameter...
public virtual IDbDataParameter AddDbParmSpecificValue(string ParmName, object UnknownValue)
{ throw new Exception("AddDbParmSpecificValue() method must be overwritten per specific connection."); }
// generic "Connection" since they are all based on IDbCommand...
public override bool SQLConnect()
{
// pre-blank exception in case remnant from previous activity
LastException = null;
if (sqlConnectionHandle.State != System.Data.ConnectionState.Open)
try
{
// if not open, always make sure we get updated connection string
// if ever changed by some other "unknown" condition...
sqlConnectionHandle.ConnectionString = GetConnectionString();
sqlConnectionHandle.Open();
}
catch (Exception ex)
{
// Preserve in generic sqlException" property for analysis OUTSIDE this function
LastException = ex;
}
// if NOT connected, display message to user and set error code and exception
if (sqlConnectionHandle.State != System.Data.ConnectionState.Open)
LastException = new Exception("Unable to open database connection.");
// return if it IS successful at opening the connection (or was already open)
return sqlConnectionHandle.State == System.Data.ConnectionState.Open;
}
// likewise disconnect could be common
public void SQLDisconnect()
{
if (sqlConnectionHandle != null)
if (sqlConnectionHandle.State == ConnectionState.Open)
sqlConnectionHandle.Close();
}
public bool SqlExecNonQuery( IDbCommand SQLCmd, DataTable oTbl)
{
// pre-clear exception
LastException = null;
// fill the table...
SQLConnect();
try
{
RowsAffectedByQuery = SQLCmd.ExecuteNonQuery();
}
catch (Exception e)
{
LastException = e;
throw e;
}
finally
{
SQLDisconnect();
}
// Its all ok if no exception error
return LastException == null;
}
}
// Now, build your connection manager per specific type
public class MyAccessConnection : MyConnection
{
public MyAccessConnection()
{ sqlConnectionHandle = new OleDbConnection(); }
public override string GetConnectionString()
{ return "Your Connection String from AppSettings.. any changes if OleDb vs SQL"; }
public override IDbCommand GetSQLDbCommand()
{ return new OleDbCommand( "", (OleDbConnection)sqlConnectionHandle ); }
public override IDbDataParameter AddDbParmSpecificValue(string ParmName, object UnknownValue)
{ return new OleDbParameter( ParmName, UnknownValue ); }
}
public class MySQLConnection : MyConnection
{
public MySQLConnection()
{ sqlConnectionHandle = new SqlConnection(); }
public override string GetConnectionString()
{ return "Your Connection String from AppSettings... any alterations needed??? "; }
public override IDbCommand GetSQLDbCommand()
{ return new SqlCommand ("", (SqlConnection)sqlConnectionHandle); }
public override IDbDataParameter AddDbParmSpecificValue(string ParmName, object UnknownValue)
{ return new SqlParameter(ParmName, UnknownValue); }
}
// Now to implement... pick one... Access or SQL-Server for derivation...
public class MyDataLayer : MyAccessConnection
{
public void SomeSQLCall()
{
IDbCommand sqlcmd = GetSQLDbCommand();
sqlcmd.CommandText = "UPDATE TileTypes SET Title = #Title, "
+ "Picture = #Picture, "
+ "Color = #Color "
+ "WHERE ID = #ID";
sqlcmd.Parameters.Add( AddDbParmSpecificValue( "#Title", titleTextBox.Text.Trim() ));
sqlcmd.Parameters.Add( AddDbParmSpecificValue( "#Picture", typePictureBox.ImageLocation) );
sqlcmd.Parameters.Add( AddDbParmSpecificValue( "#Color", colorButton.BackColor.ToArgb()) );
sqlcmd.Parameters.Add( AddDbParmSpecificValue( "#ID", id));
if( SqlExecNonQuery(sqlcmd))
// Good to go
DoSomethingWithTheData;
else
// Notify of whatever error thrown....
}
}
}
So.. as you can see, my last class specifically is derived from EITHER Access OR SQL. Then, I can create my methods to get data, call updates, whatever. Get a SQL Command (which returns proper type and automatically is attached to its corresponding "Connection Handle" object, prepare the text, add your parameters, execute it.

Return value from USING statement

Originally this method returns false only in case of ANY problems regardless of their type. I'm wondering will applying using statement break the logic if exception
Is it ok to return true value from the using statement in this manner:
try
{
Measurements.DeleteAllMeasurements(ID);
string query = "DELETE FROM `Narz` WHERE `NAZk_1_ID`=#NAZ_ID";
using(OleDbConnection strukturaConnection = new OleDbConnection(CommonConnectionString + DbPath + strStructureMdb))
{
using (OleDbCommand command = new OleDbCommand(query, strukturaConnection);)
{
command.Parameters.Add("#NAZ_ID", OleDbType.Numeric, 50);
command.Parameters["#NAZ_ID"].Value = ID;
command.ExecuteNonQuery();
return true;
}
}
}
catch (Exception ex)
{
Logger.LogError(ex);
return false;
}
Or I should return false in another way?
All the using statement does is implicitly call the instance's implementation of IDisposable.Dispose() at the end of the code block.
Unless you are returning a reference and the Dispose() method happens to manipulate it, then the two concerns are completely unrelated.
In short, it doesn't matter what value you return from within a using statement.
Edit: About what your method "should return": We don't have enough information to know this. We don't even know what the name of the method is. And we don't know by what other objects or aspects of the application the method will be used. The return value should be meaningful to its caller, and effectively communicate the result of the operation.
Instead create a bool value when method creates. Inside try set its value to true and in catch set its value to false. Outside catch return that variable value.
Using will have no affect on your code or mine. It is just for calling IDisposable.Dispose() implicitly.
that'll be fine - all its doing is calling the dispose method of the IDisposable object in the using statement parentheses

Workaround for ASP throwing MySQL exception

This is going to take some explaining. I'm new to ASP, having come from PHP. Completely different world. Using the MySql Connecter/Net library, I decided to make a database wrapper which had a fair amount of fetch methods, one being a "FetchColumn()" method which simply takes a string as its parameter and uses the following implementation:
public object FetchColumn(string query)
{
object result = 0;
MySqlCommand cmd = new MySqlCommand(query, this.connection);
bool hasRows = cmd.ExecuteReader().HasRows;
if (!hasRows)
{
return false;
}
MySqlDataReader reader = cmd.ExecuteReader();
int count = 0;
while(reader.HasRows)
{
result = reader.GetValue(count);
count++;
}
return result;
}� return result;
}public object FetchColumn(string query)
What I'm looking for is a way to return false IF and only IF the query attempts to fetch a result which doesn't exist. The problem is that, with my implementation, it throws an error/exception. I need this to "fail gracefully" at run time, so to speak. One thing I should mention is that with this implementation, the application throws an error as soon as the boolean "hasRows" is assigned. Why this is the case, I have no idea.
So, any ideas?
It's hard to say for sure, since you didn't post the exact exception that it's throwing, but I suspect the problem is that you're calling ExecuteReader on a command that is already in use. As the documentation says:
While the MySqlDataReader is in use, the associated MySqlConnection is busy serving the MySqlDataReader. While in this state, no other operations can be performed on the MySqlConnection other than closing it. This is the case until the MySqlDataReader.Close method of the MySqlDataReader is called.
You're calling cmd.ExecuteReader() to check to see if there are rows, and then you're calling ExecuteReader() again to get data from the rows. Not only does this not work because it violates the conditions set out above, it would be horribly inefficient if it did work, because it would require two trips to the database.
Following the example shown in the document I linked, I'd say what you want is something like:
public object FetchColumn(string query)
{
MySqlCommand cmd = new MySqlCommand(query, this.connection);
MySqlDataReader reader = cmd.ExecuteReader();
try
{
bool gotValue = false;
while (reader.Read())
{
// do whatever you're doing to return a value
gotValue = true;
}
if (gotValue)
{
// here, return whatever value you computed
}
else
{
return false;
}
}
finally
{
reader.Close();
}
}
I'm not sure what you're trying to compute with the HasRows and the count, etc., but this should get you pointed in the right direction.
you need to surround the error throwing code with a try clause
try {
//The error throwing Code
}
catch (exception e)
{
//Error was encountered
return false
}
If the error throwing code throws and error the catch statement will execute, if no error is thrown then the catch statement is ignored
First of all do a try and catch
try
{
//code
}
catch (Exception exp)
{
//show exp as message
}
And the possible reason of your error is that your mysql query has errors in it.
try executing your query directly in your mysql query browser and you'll get your answer.
If its working fine then double check your connection string if its correct.
NOTE:mark as answer if it solves your issue

Categories