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
Related
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;
}
I have some code which looks like this:
Object o;
using (SqlConnection sql = GetSqlConnection) {
using (SqlCommand sqlCommand = GetSqlCommand()) {
using (Datareader dr = GetDataReader()) {
o = new Object();
while (dr.read()) {
//do something
}
}
if (o == null) // RESHARPER SAYS THAT THIS WILL ALWAYS BE TRUE
//do something
}
}
The place where I check for o == null, ReSharper says that this command will always be true. I don't understand this behaviour; do all the objects initialised in using block get disposed of, or only the ones which are created with using statement.
When the using block is closed, it will call Dispose() on that object, which, depending on the implementation of IDisposable, may set the object to null. However, "o" in your case isn't IDisposable or in a using block, and I'm willing to believe ReSharper has a bug in this case, because when I have the exact same code in my installation, it prompts me to replace
if(o == null)
with false, exactly the opposite of your problem.
If your code is exactly as written and Resharper is really complaining about the line you indicated, then it is wrong.
In fact, ReSharper has it exactly backwards: the comparison is redundant because it will never be true. You set o to a new Object() immediately, so it will never be null. The using block has no effect on the value of variables other than the one you put in the opening statement. Upon leaving a using block, that one instance is disposed of by calling IDisposable.Dispose on it, and it goes out of scope.
However, I do want to correct one huge misconception you seem to have: disposing of an object does not set it to null. The following code will still crash when it tries to close an already-disposed object:
var conn = new SqlConnection(GetConnectionString());
conn.Open();
conn.Dispose();
if (conn != null)
{
conn.Close();
}
"Being disposed" is a condition that applies to instances of objects; it means their resources have been cleaned up and they cannot be safely used anymore. "Being null" is a condition that applies to variables; it means they do not reference any instance of their defined type, disposed-of or otherwise.
The using keyword and IDisposable interface are using to manage the is-disposed-of state of instances of objects. They have no effect on the is-a-null-value state of variables in your program.
Does initialising an object in “using” block disposes it of outside
the block?
No. Here is proof.
The object you're using will be disposed, of course (that's the whole point of using), but things done within the block aren't affected. This is a new scope, though, so you'd get the warning with this code:
Object o;
using (SqlConnection sql = GetSqlConnection) {
using (SqlCommand sqlCommand = GetSqlCommand()) {
using (Datareader dr = GetDataReader()) {
Object o = new Object();
while (dr.read()) {
//do something
}
}
if (o == null) // RESHARPER SAYS THAT THIS WILL ALWAYS BE TRUE
//do something
}
}
(note the declaration of a second object o in the inner scope).
I was searching the web for a while now. But didn't find any clear answer to my question. Whether when connecting to a database I should use "using" or I can just go with try-catch-finally? What I mean is:
I don't know if I should call the dispose method each time I finish interacting with the database or just close the connection.
static public List<Category> GetAll()
{
List<Category> CategoryList;
try
{
BaseDAO.Dbconn.Open();
BaseDAO.SetCommand(BaseDAO.CommandAction.Read, "SELECT * FROM Categories");
CategoryList = new List<Category>();
using (DbDataReader reader = BaseDAO.Dbcmd.ExecuteReader())
{
while (reader.Read())
{
int ID = reader.GetInt32(reader.GetOrdinal("CategoryID"));
string Name = reader.GetString(reader.GetOrdinal("CategoryName"));
string Description = reader.GetString(reader.GetOrdinal("Description"));
CategoryList.Add(new Category(ID, Name, Description));
}
}
return CategoryList;
}
catch (Exception ex)
{
BaseDAO.Dbconn.Dispose();
throw ex;
}
finally { BaseDAO.Dbconn.Close(); }
}
The "Dbconnection" is static not sure if this is a good solution as well...
I am getting to know ADO and just wanted to know what's the best answer for this kind of question.
It doesn't make any difference - whatever you prefer. The using clause gets turned into a try-finally by the compiler anyway.
EDIT I just noticed you are only calling Dispose if an exception occurs. You should move this into the finally clause as well. Dispose will call Close, so you don't need to specifically call it if you don't want to.
Further edit Given that, as you say, your DbConnection is static, then you don't want to call Dispose, but you do need to call Close. However, there should not be any need to use a static DbConnection - connection pooling will take care of efficiently handling the connections. Your code should create a new connection instance every time.
Reference: Using Statement C#.
The using statement allows the programmer to specify when objects that use resources should release them.
The object provided to the using statement must implement the
IDisposable interface. This interface provides the Dispose method,
which should release the object's resources.
A using statement can be exited either when the end of the using statement is reached or if an exception is thrown and control leaves the statement block before the end of the statement.
Reference : Example
As per Code Project, the .NET CLR converts
using (MyResource myRes = new MyResource())
{
myRes.DoSomething();
}
to:
{
// limits scope of myRes
MyResource myRes= new MyResource();
try
{
myRes.DoSomething();
}
finally
{
// Check for a null resource.
if (myRes!= null)
// Call the object's Dispose method.
((IDisposable)myRes).Dispose();
}
}
Calling Dispose is equivalent to calling Close in most (if not all) DbConnection implementations, so there's no need to call the former if you are already calling the latter. Just make sure you do so in a finally in case there's an 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
Suppose that I have the following code:
private void UpdateDB(QuoteDataSet dataSet, Strint tableName)
{
using(SQLiteConnection conn = new SQLiteConnection(_connectionString))
{
conn.Open();
using (SQLiteTransaction transaction = conn.BeginTransaction())
{
using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM " + tableName, conn))
{
using (SQLiteDataAdapter sqliteAdapter = new SQLiteDataAdapter())
{
sqliteAdapter.Update(dataSet, tableName);
}
}
transaction.Commit();
}
}
}
The C# documentation states that with a using statement the object within the scope will be disposed and I've seen several places where it's suggested that we don't need to use try/finally clause.
I usually surround my connections with a try/finally, and I always close the connection in the finally clause. Given the above code, is it reasonable to assume that the connection will be closed if there is an exception?
You are correct; the using statement compiles to a try / finally block.
The compiler transforms using(resource) statement; into the following code:
{
ResourceType resource = expression;
try {
statement;
}
finally {
if (resource != null) ((IDisposable)resource).Dispose();
}
}
(The cast to IDisposable is in case ResourceType implements IDisposable explicitly.
Yes, you either need to use a try/finally or a using statement. You don't need both.
A using statement is almost the same as a try/finally except that in C# 3 you can't reassign to the variable inside the using block.
using (IDisposable d = foo())
{
d = null; // Error: Cannot assign to 'd' because it is a 'using variable'
}
Previously you could reassign but the original object would still be disposed, not the newly assigned object and you would also get this compile warning:
Possibly incorrect assignment to local 'd' which is the argument to a using or lock statement. The Dispose call or unlocking will happen on the original value of the local.
Yes, the using statement is pretty much just shorthand for a try ... finally block.
For example, this code...
using (MyDisposableType foo = new MyDisposableType())
{
foo.DoSomething();
}
...would equate to the following...
{
MyDisposableType foo = new MyDisposableType();
try
{
foo.DoSomething();
}
finally
{
if (foo != null)
((IDisposable)foo).Dispose();
}
}
You can assume that the connection will be closed if you get an exception.
Using() ensures that the item instantiated within the parameters will be disposed of regardless of that happens within the associated code block. This includes closing the database connection assuming that SQLiteConnection handles its disposal correctly.