In one of my previous questions someone suggested that instead of using trycatch and closing the connection at finally I should just use "using". Can someone give me an example?
I have this code, how do I use just "using" with it?
try
{
conn3.Open();
string sql_check = "SELECT (time_in) FROM timeinout WHERE employee_id = #employee_id AND date = #date";
using var cmd_check = new NpgsqlCommand(sql_check, conn3);
cmd_check.Parameters.AddWithValue("employee_id", id);
cmd_check.Parameters.AddWithValue("date", date);
cmd_check.Prepare();
var reader = cmd_check.ExecuteReader();
if (reader.Read())
{
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
finally
{
conn3.Close();
}
using is not a replacement for try...catch...finally. It enables you to do away with the finally block but, if an exception can be thrown, you still need to catch it. The using block guarantees that the object created will be disposed, whether an exception is thrown or not. This:
var obj = new SomeType();
try
{
// Use obj here.
}
catch
{
// Handle exception here.
}
finally
{
obj.Dispose();
}
can AND SHOULD be replaced with this:
using (obj = new SomeType())
{
try
{
// Use obj here.
}
catch
{
// Handle exception here.
}
}
Basically, if already have exception handling then you still need exception handling but you don't need to close/dispose locally-created objects in a finally block. If you're doing anything else in your finally block then you still need it too.
In your case, you should be creating your connection, command and data reader with using statements:
using (var connection = new NpgsqlConnection(connectionString))
using (var command = new NpgsqlCommand(query, connection))
{
try
{
connection.Open();
using (var reader = command.ExecuteReader())
{
return reader.HasRows;
}
}
catch
{
return false;
}
}
The data reader will be closed at the end of the inner using block and the connection will be closed at the end of the outer using block.
Related
I have question regarding Entity Framework. In my program I first fill-up my DbContext with data. Then I need to delete all the data from the tables in DB, but only if new data will be saved. If db.Savechanges() throws an exception I need my old data to still be in the tables.
My code is:
static void Main(string[] args)
{
PdmContext db = new PdmContext();
FillDbContext();
try
{
if (db.SaveChanges() > 0)
{
using (var del = new PdmContext())
{
DeleteModel.deleteFromAllTables();
}
db.SaveChanges();
}
}
catch (Exception exp)
{
Logger.Log("Exception (global catch));
}
}
I can't seem to figure this out. Anyone can help with this? :)
You can use Transaction which will make sure to revert the operation done within the scope of it if the operation fails at some stage :
using (var scope = new TransactionScope(TransactionScopeOption.Required))
{
using (var del = new PdmContext())
{
DeleteModel.deleteFromAllTables();
}
db.SaveChanges();
scope.Complete(); // commits the transaction
}
Now the changes to the database will be atomic so that it will only keep all changes or not at all. I have not included exception handling code for simplicity but due to any reason if the scope.Complete() was not being executed and control exists the transaction block without executing that the transaction will get rolled back.
You need to use a Transaction.
see how to use that:
using (var dbContextTransaction = PdmContext.Database.BeginTransaction())
{
try
{
// HERE your operation insert etc.
PdmContext.SaveChanges();
dbContextTransaction.Commit(); // here, apply your operation
}
catch (Exception)
{
dbContextTransaction.Rollback(); // here, undo your operations
}
}
You can handle such scenario with transaction management.
There is two way to handle it.
1) You can use single dbcontext for all operation instead of create multiple for single operation.
using (var context = new SchoolContext())
{
try
{
context.Students.Add(new Student()
{
FirstName = "Rama2",
StandardId = standard.StandardId
});
context.Courses.Add(new Course() { CourseName = "Computer Science" });
context.SaveChanges();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
Console.WriteLine("Error occurred.");
}
}
2) Using single DbContextTransaction object:
using (var context = new SchoolContext())
{
context.Database.Log = Console.Write;
using (DbContextTransaction transaction = context.Database.BeginTransaction())
{
try
{
context.Students.Add(new Student()
{
FirstName = "Rama2",
StandardId = standard.StandardId
});
context.SaveChanges();
context.Courses.Add(new Course() { CourseName = "Computer Science" });
context.SaveChanges();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
Console.WriteLine("Error occurred.");
}
}
}
I hope it work for you.
lib.ParamsInsert is called via another dll.
The transaction is rolled back when there is a problem with the throw statement. However, the operations in paramsInsert can not be undone.
In lib.ParamsInsert, there is a transaction in its own error.
spcarikart.Repository lib = new spcarikart.Repository();
using (var transaction = db.Database.BeginTransaction())
{
try
{
var result = db.Acenta.Add(obj).Entity;
var a = lib.ParamsInsert(db, new Params
{
Baslik = "Bahdir",
Deger = "1"
});
// ....Maybe Error other process
db.SaveChanges();
return result;
}
catch (Exception ex)
{
transaction.Rollback();
}
}
ParamsInsert
using (var transaction = db.Database.BeginTransaction())
{
try
{
var resul = db.Params.Add(obj).Entity;
db.SaveChanges();
transaction.Commit();
return resul;
}
catch (Exception ex)
{
transaction.Rollback();
throw new Exception();
}
}
They use different transactions. Don't start new transaction, as I see, you work with the same db context, so needn't start transaction in paramsInsert, remove using (var transaction = db.Database.BeginTransaction()) from it.
I'm learning how Dapper is working behind the scenes.
However I saw this pattern of disposing which is not understood to me.
Roughly in general — this is how QueryAsync is implemented :
/*1*/ public async Task<IEnumerable<T>> QueryAsync<T>(string sql, Func<IDataRecord, T> projector, DbConnection _conn, dynamic param = null)
/*2*/ {
/*3*/
/*4*/ DbDataReader reader = null;
/*5*/ bool wasClosed = _conn.State == ConnectionState.Closed;
/*6*/ try
/*7*/ {
/*8*/
/*9*/ using (var cmd = _conn.CreateCommand())
/*10*/ {
/*11*/ if (param!=null)
/*12*/ foreach (var prop in param.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
/*13*/ {
/*14*/ var parameter = cmd.CreateParameter();
/*15*/ parameter.ParameterName = prop.Name;
/*16*/ parameter.Value = prop.GetValue(param, null);
/*17*/ cmd.Parameters.Add(parameter);
/*18*/ }
/*19*/
/*20*/ await _conn.OpenAsync().ConfigureAwait(false);
/*21*/ cmd.CommandTimeout = 100000;
/*22*/ cmd.CommandText = sql;
/*23*/ reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false);
/*24*/ List<T> buffer = new List<T>();
/*25*/ while (await reader.ReadAsync().ConfigureAwait(false)) buffer.Add(projector(reader));
/*26*/ return buffer;
/*27*/ }
/*28*/
/*29*/ }
/*30*/ finally
/*31*/ {
/*32*/ using (reader) { }
/*33*/ if (wasClosed) _conn.Close();
/*34*/ }
/*35*/ }
I can understand why he didn't use using over the connection , that's because he wanted to conditionally close the connection via the wasClosed variable.
For doing it - he must use the try/finally clause. ( so the conditional closing will be in the finally clause)
But my question is about line #32.
Instead of doing using at the finally clause , he could do:
using (DbDataReader reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false))
{
List<T> buffer = new List<T>();
while (await reader.ReadAsync().ConfigureAwait(false)) buffer.Add(projector(reader));
return buffer;
}
So the finally clause is left with :
finally
{
//using (reader) { } //removed
if (wasClosed) _conn.Close();
}
Question
I've seen this using clause in a finally clause many times in dapper.
I must be missing something here, But what does this pattern achieve that my suggestion does not?
I'm no #MarcGravell, but I think there is one thing you're missing. The code you pasted doesn't exactly match the link you reference. The relevant code path looks like this:
try
{
if (command.Buffered)
{
List<T> buffer = new List<T>();
while (await reader.ReadAsync(cancel).ConfigureAwait(false))
{
buffer.Add((T)func(reader));
}
while (await reader.NextResultAsync().ConfigureAwait(false)) { }
command.OnCompleted();
return buffer;
}
else
{
// can't use ReadAsync / cancellation; but this will have to do
wasClosed = false; // don't close if handing back an open reader;
// rely on the command-behavior.
var deferred = ExecuteReaderSync<T>(reader, func, command.Parameters);
reader = null; // to prevent it being disposed before the caller gets to see it
return deferred;
}
}
finally
{
using (reader) { } // dispose if non-null
if (wasClosed) cnn.Close();
}
The method can either return a buffered result (indicated by the command.Buffered flag) or a deferred iterator. If Marc was to wrap the reader with a using statement and return an iterator, it (the reader) would of been disposed by the time the call-site executed it. By setting the reader to null (in the line before he returns the deferred result) he prevents the reader from being disposed, because the using in the finally block would be translated to this:
finally
{
IDisposable disposable = reader;
try
{
}
finally
{
if (dispoable != null)
{
disposable.Dispose();
}
}
}
When he sets the reader to null, it isn't disposed, and the reference exists in the iterator is still alive, pointing to the reader. This way, he can both dispose the reader in the normal codepath, but keep it alive if a deferred iterator was requested.
The use of FBConnection is giving me some trouble.
In examples of the Firebird Ole-Db I find only examples using a static main method, but I'm not sure how to implement the use of an FbConnection in instance methods.
Right now I'm initializing and using the connection as shown in the code example below.
Every now and then I get the error "connectionstring is not initialized". The connection object is not null, but the connectionstring seems to be null.
What causes this behaviour? Should I reinitialize the FbConnect object every time I access the method (making it a local variable), or is this performance-wise a very bad idea?
public class MyUserStore<TUser> : IUserPasswordStore<TUser, int>, IUserStore<TUser, int>, IDisposable where TUser : ApplicationUser, new()
{
private FbConnection Connection = new FbConnection("User=-----;" +
"Password=-------;" +
"Database=C:\\------\\Testing.GDB;" +
"DataSource=localhost;" +
"Dialect=3;Charset=NONE;");
public Task<TUser> FindByIdAsync(int userId)
{
if (userId == 0)
{
throw new ArgumentNullException("userId");
}
TUser User = null;
if (Connection != null)
{
FbTransaction transaction = null;
FbDataReader Reader = null;
using (Connection)
{
try
{
Connection.Open();
FbCommand Command = new FbCommand(GetByIdQuery, Connection);
Command.Parameters.AddWithValue("id", userId);
Reader = Command.ExecuteReader();
catch (Exception e)
{
if (transaction != null)
{
transaction.Rollback();
}
System.Diagnostics.Debug.WriteLine(e.StackTrace);
return Task.FromResult<TUser>(null);
}
finally
{
if (Reader != null)
{
Reader.Close();
}
Connection.Close();
}
}
}
}
Mark Rotteveel is right in his comment.
Apparently, the using clause means the resource is being disposed of right at the end of the block. This means I would need to create a new connection every time I use the "using" block.
I am attempting to read a MySQL database from my C# project using the MySQL drivers for .net off the MySQL site.
Though I did a bit of research on this (including this), I am still flummoxed why this is happening. I later ran a spike and I still get the same error. (Prior to running this I populated the database with some default values.) Here's the spike code in toto.
class Program {
static void Main (string[] args) {
Console.WriteLine (GetUserAge ("john")); // o/p's -1
}
static int GetUserAge (string username) {
string sql = "select age from users where name=#username";
int val = -1;
try {
using (MySqlConnection cnn = GetConnectionForReading ()) {
cnn.Open ();
MySqlCommand myCommand = new MySqlCommand (sql, cnn);
myCommand.Parameters.AddWithValue ("#username", username);
using (MySqlDataReader reader = myCommand.ExecuteReader ()) {
DataTable dt = new DataTable ();
dt.Load (reader);
if (reader.Read ()) {
val = reader.GetInt32 (0);
}
}
}
} catch (Exception ex) {
Console.WriteLine (ex.Message);
} finally {
}
return val;
}
private static MySqlConnection GetConnectionForReading () {
string conStr = "Data Source=localhost;Database=MyTestDB;User ID=testuser;Password=password";
return new MySqlConnection (conStr);
}
}
The code above gives me the exception: "Invalid attempt to Read when reader is closed."
Later I modified the if-condition like so:
if (reader.HasRows && reader.Read ()) {
val = reader.GetInt32 (0);
}
And now the o/p is -1. (The data's in there in the table.) If for some reason the result set had zero rows, the reader should not have got into the if-block in the first place. I mean, the whole point of the Read() method is to check if there are any rows in the result set in the first place.
At my wit's end here... just cannot figure out where I'm going wrong.
Thank you for your help! :)
I think using DataTable.Load will "consume" the reader and, at the very least, position it at the end. It may even account for the closed connection (but I'm just guessing here). What if you remove that line? I don't think it makes any sense here.