explicitly dispose NpgsqlParameters - c#

Do I really need to explicitly dispose of NpgsqlParameters?
Code I am using goes below:
using (var connection = new NpgsqlConnection(connectionstring))
{
connection.Open();
using (var command = new NpgsqlCommand())
{
command.Connection = connection;
command.CommandText = "Select * from mytable where column1=:pcolumn1 AND column2=:pcolumn2";
command.Parameters.AddRange(new NpgsqlParameter[2]{
new NpgsqlParameter{ ParameterName="pcolumn1", Value=val1},
new NpgsqlParameter{ ParameterName="pcolumn2", Value=val2}
});
using (var reader=command.ExecuteReader())
{
while (reader.Read())
{
//read reader here
}
}
}
}

NpgsqlParameter is inherited from DbParameter and ICloneable. Neither of these implement IDisposable so you don't need to dispose NpgsqlParameters.

Related

Automapper to read single record

I have been trying to read single Record using AutoMapper. But I couldn't get through using the below code,
public ChartOfAccount GetSingleCOA( )
{
string queryString = "select * from ChartofAccounts where AccNo=423";
using (var connection = new SqlConnection(conStr))
using (var command = new SqlCommand(queryString, connection))
{
connection.Open();
using (var reader = command.ExecuteReader())
if (reader.HasRows)
{
reader.Read();
return Mapper.Map<IDataRecord, ChartOfAccount>(reader);
}
}
return null;
}
simply changing the line to
return Mapper.DynamicMap<IDataReader, ChartOfAccount>(reader);
solved the issue

There is already an open DataReader associated with this Command which must be closed first npgsql c#

I made my reader.close() and it does not work as well.
can you help me to resolve my problem.
IList<Borne> ListeBorne = new List<Borne>();
NpgsqlCommand maCommande2 = new NpgsqlCommand("Select * from borne;", conn);
NpgsqlDataReader monReader2 = maCommande2.ExecuteReader(CommandBehavior.CloseConnection);
NpgsqlCommand maCommandeEncaiss= new NpgsqlCommand("Select * from encaissement;", conn);
NpgsqlDataReader monReaderEncaiss = maCommandeEncaiss.ExecuteReader(CommandBehavior.CloseConnection);
while (monReaderEncaiss.Read())
{
Encaissement encaiss = new Encaissement();
encaiss.id = monReaderEncaiss.GetInt32(0);
encaiss.mode_paiemant = monReaderEncaiss.GetString(2);
encaiss.num_fact = monReaderEncaiss.GetString(9);
ListEncaissement.Add(encaiss);
}
while (monReader2.Read())
{
Borne b = new Borne();
b.id = monReader2.GetInt32(0);
b.nom = monReader2.GetString(2);
ListeBorne.Add(b);
}
ViewBag.ref_borne = new SelectList(ListeBorne, "id", "nom");
ViewBag.num_fact = new SelectList(ListEncaissement, "id", "num_fact");
ViewBag.mode_paiement = new SelectList(ListEncaissement, "id", "mode_paiemant");
I added preload reader = true in connectionString web config but it did not work yet.
You have to close a reader before you can use another on the same connection.
You should use the using-statement for anything implementing IDisposable whenever possible:
using (var conn = new NpgsqlConnection("connection-string"))
{
using (var command = new NpgsqlCommand("Select * from encaissement", conn))
{
conn.Open();
using (NpgsqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
var encaiss = new Encaissement();
encaiss.id = reader.GetInt32(0);
encaiss.mode_paiemant = reader.GetString(2);
encaiss.num_fact = reader.GetString(9);
ListEncaissement.Add(encaiss);
}
}
}
using (var command = new NpgsqlCommand("Select * from borne", conn))
{
using (NpgsqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
var b = new Borne();
b.id = reader.GetInt32(0);
b.nom = reader.GetString(2);
ListeBorne.Add(b);
}
}
}
}
"While the SqlDataReader is being used, the associated SqlConnection is busy serving the SqlDataReader, and no other operations can be performed on the SqlConnection other than closing it." - msdn.
Normally you might have to manually close a connection. But if you use CommandBehavior.CloseConnection the "Connection object is closed when the associated DataReader object is closed." - msdn.
IList<Borne> ListeBorne = new List<Borne>();
NpgsqlCommand maCommandeEncaiss= new NpgsqlCommand("Select * from encaissement;", conn);
NpgsqlDataReader monReaderEncaiss = maCommandeEncaiss.ExecuteReader(CommandBehavior.CloseConnection);
while (monReaderEncaiss.Read())
{
Encaissement encaiss = new Encaissement();
encaiss.id = monReaderEncaiss.GetInt32(0);
encaiss.mode_paiemant = monReaderEncaiss.GetString(2);
encaiss.num_fact = monReaderEncaiss.GetString(9);
ListEncaissement.Add(encaiss);
}
monReaderEncaiss.Close();
NpgsqlCommand maCommande2 = new NpgsqlCommand("Select * from borne;", conn);
NpgsqlDataReader monReader2 = maCommande2.ExecuteReader(CommandBehavior.CloseConnection);
while (monReader2.Read())
{
Borne b = new Borne();
b.id = monReader2.GetInt32(0);
b.nom = monReader2.GetString(2);
ListeBorne.Add(b);
}
monReader2.Close();
etc...

ADO.NET ExecuteReader Returns No Results

I'm updating some old legacy code and I ran into a problem with the
SqlCommand.ExecuteReader() method. The problem is that it's not returning any
results. However, using SqlDataAdapter.Fill(), I get results back from the
database. What am I doing wrong? How can I get results back using the data
reader?
var connectionString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ToString();
using (var sqlConnection = new SqlConnection(connectionString))
{
using (var sqlCommand = new SqlCommand())
{
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandType = CommandType.Text;
sqlCommand.CommandText = "SELECT * FROM MyTable WHERE ID = 1";
sqlConnection.Open();
// This code works.
//var dataTable = new DataTable();
//using (var sqlDataAdapter = new SqlDataAdapter(sqlCommand))
//{
// sqlDataAdapter.Fill(dataTable);
//}
// This code is not working.
using (var sqlDataReader = sqlCommand.ExecuteReader())
{
while (sqlDataReader.Read())
{
// This fails because the data reader has no results.
var id = sqlDataReader.GetInt32(0);
}
}
}
}
Could it be that there is no Int32 in your results ?
var id = sqlDataReader.GetInt32(0); // <-- this might not be an Int32
Either try:
var id = sqlDataReader.GetValue(0);
Or cast to the correct type (BIGINT for example is Int64), not sure without seeing your data.
Try this..
var id = 0;
using (var sqlDataReader = sqlCommand.ExecuteReader())
{
while (sqlDataReader.Read())
{
id = sqlDataReader.GetInt32(sqlDataReader.GetOrdinal("ColName"));
}
}
I have moved the variable outside of the reader code or the variable will only be accessible inside that scope. I would avoid specifying the ordinal in the code, in case someone altered the columns in the DB.
Also, specify the columns in the SQL statement... SELECT ColName FROM ... and use params in the query
If you got to that line then it has results
Does not mean the value is not null
And you should not use a SELECT *
If may have a problem with an implicit cast
Try Int32
try
{
if(sqlDataReader.IsDBNull(0))
{
// deal with null
}
else
{
Int32 id = sqlDataReader.GetInt32(0);
}
}
catch (SQLexception Ex)
{
Debug.WriteLine(Ex.message);
}
var connectionString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ToString();
using (var sqlConnection = new SqlConnection(connectionString))
{
sqlConnection.Open();
string sql = "SELECT * FROM MyTable WHERE ID = 1";
using (var sqlCommand = new SqlCommand(sql, sqlConnection))
{
using (var sqlDataReader = sqlCommand.ExecuteReader())
{
while (sqlDataReader.Read())
{
// This fails because the data reader has no results.
var id = sqlDataReader.GetInt32(0);
}
}
}
}

How to use Using statement for multiple instances?

I want to use using for SqlConnection and SqlCommand objects to dispose those. How can I use in this scenario?
for example:
using (sqlConnection = new SqlConnection(IRLConfigurationManager.GetConnectionString("connectionStringIRL")))
{
}
But here I am using connection based on the if condition.
SqlConnection _sqlConnection;
SqlCommand sqlCmd;
DBPersister per = (DBPersister)invoice;
if (per == null)
{
_sqlConnection = new SqlConnection(IRLConfigurationManager.GetConnectionString("connectionStringIRL"));
sqlCmd = new SqlCommand("usp_UpdateDocumentStatusInImages", _sqlConnection);
}
else
{
_sqlConnection = per.GetConnection();
sqlCmd = per.GenerateCommand("usp_UpdateDocumentStatusInImages", _sqlConnection, per);
}
sqlCmd.CommandType = CommandType.StoredProcedure;
//mycode
try
{
if (_sqlConnection.State == ConnectionState.Closed)
_sqlConnection.Open();
sqlCmd.ExecuteNonQuery();
}
catch
{
throw;
}
finally
{
if (per == null)
invoice._sqlConnection.Close();
}
You can nest them, like this:
using (var _sqlConnection = new SqlConnection(...))
{
using (var sqlCmd = new SqlCommand(...))
{
//code
}
}
Use the conditional operator to determine what to assign to each variable:
using(SqlConnection _sqlConnection = per==null?
new SqlConnection(IRLConfigurationManager.GetConnectionString("connectionStringIRL"))
: per.GetConnection())
using(SqlCommand sqlCmd = per==null?
new SqlCommand("usp_UpdateDocumentStatusInImages", _sqlConnection);
: per.GenerateCommand("usp_UpdateDocumentStatusInImages",
_sqlConnection, per))
{
//Code here using command and connection
}
Although I must say, per.GenerateCommand(..., per) looks like an odd function (it's an instance method that also must be passed an instance of the same class - must it always be the same instance?)

How can I populate a list with values from a SQL Server database?

The list will grow and shrink depending on how many items I have in my database.
I need to populate a list not a listbox. I understand I will need to open a connection.
using (var conn = new SqlConnection(Properties.Settings.Default.DBConnectionString))
{
using (var cmd = conn.CreateCommand())
{
conn.Open();
List<string> TagList = new List<string>();
for (int i = 0; i < TagList.Count; i++)
TagList[i].Add("Data from database");
cmd.ExecuteNonQuery();
}
}
I'm really not sure how to do this and I'm sure my method up here looks very wrong so I really need help.
Could someone show me what I'm doing wrong?
public IEnumerable<string> GetTagList()
{
using (var connection = new SqlConnection(Properties.Settings.Default.DBConnectionString))
using (var cmd = connection.CreateCommand())
{
connection.Open();
cmd.CommandText = "select Tag from TagsTable"; // update select command accordingly
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
yield return reader.GetString(reader.GetOrdinal("Tag"));
}
}
}
}
then you can call it as below
List<string> tags = GetTagList().ToList();
I would like to share my solution, hope helps someone in the future:
public List<string> getFromDataBase()
{
List<string> result = new List<string>();
using(SqlConnection con = new SqlConnection("connectionString"))
{
con.Open();
DataTable tap = new DataTable();
new SqlDataAdapter(query, con).Fill(tap);
result = tap.Rows.OfType<DataRow>().Select(dr => dr.Field<string>("columnName")).ToList();
}
return result;
}
This would do as it is (if I didn't do any typos...)
private void LoadList()
{
List<string> tagsList = new List<string>();
using (IDbConnection connection = new SqlConnection(Properties.Settings.Default.DBConnectionString))
{
connection.Open();
using (IDbCommand command = connection.CreateCommand())
{
command.CommandText = "SELECT TAGCOLUMN FROM TAGSTABLE";
using (IDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
if (!reader.IsDBNull(0))
tagsList.Add(reader.GetString(0));
}
reader.Close();
}
}
connection.Close();
}
}
EDIT:
Of course you have to change the select statement to the correct one from your database.
I just used a pseudo one to show you what to put there.

Categories