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?)
Related
I am a bit confused on the below coding. Are they both the same? If not, which one is the best and why?
//Two using blocks for Command and Connection
using (var cn = new OracleConnection(connectionString))
using (var cmd = new OracleCommand(sql, cn))
{
}
//One using block for Command and Connection
using (var cmd = new OracleCommand(sql, new OracleConnection(connectionString)))
{
}
First assuming that you accidently added an extra ) (otherwise neither will even compile) then the first example will properly dispose of both the command and the connection where as the second will only dispose of the command.
Here is the equivalent code for the first.
OracleConnection cn = new OracleConnection(connectionString);
try
{
OracleCommand cmd = new OracleCommand(sql, cn);
try
{
// Use cmd and cn here.
}
finally
{
if(cmd != null)
((IDisposable)cmd).Dispose();
}
}
finally
{
if(cn != null)
((IDisposable)cn).Dispose();
}
and the second.
OracleCommand cmd = new OracleCommand(sql, new OracleConnection(connectionString));
try
{
// Use cmd here.
}
finally
{
if(cmd != null)
((IDisposable)cmd).Dispose();
}
Also note that you can only create multiple instances that will all get disposed in one using if they are all the same type. As the following example from the MSDN page about using shows.
using (Font font3 = new Font("Arial", 10.0f),
font4 = new Font("Arial", 10.0f))
{
// Use font3 and font4.
}
Let's assume we have an Object A which can be deleted an Object B which hold a forendkey from A
If you want to deleted A, you have to delete the forendkey from B first and then you can delete A but if something goes wrong it should be rolled back but i also want to use the delete forendkey from B independent but at the moment i don't know how to achieve this
my current idea :
public void DeleteA(Object a)
{
using (SqlConnection con = new SqlConnection())
{
con.open();
using (SqlTransaction tr = con.BeginTransaction())
{
try
{
DeleteAfromAllB(a, con, tr);
using (SqlCommand cmd = new SqlCommand("STP_A_Delete", con))
{
cmd.Transaction = tr;
// some parameters
// some sort of Execute
// e.g.: cmd.ExecuteNonQuery();
}
tr.Commit();
}
catch (SqlException ex)
{
//ExceptionHandling
}
}
}
}
private void DeleteAfromAllB(Object a, SqlConnection con, SqlTransaction tr)
{
try
{
using (SqlCommand cmd = new SqlCommand("STP_B_Delete_Referenc_To_A", con))
{
cmd.Transaction = tr;
// some parameters
// some sort of Execute
// e.g.: cmd.ExecuteNonQuery();
}
}
catch (SqlException ex)
{
//ExceptionHandling
}
}
public void DeleteAfromAllB(Object a)
{
using (SqlConnection con = new SqlConnection())
{
con.open();
using (SqlTransaction tr = con.BeginTransaction())
{
DeleteAfromAllB(a,con,tr);
tr.Commit();
}
}
}
but like you can see this is pretty ugly
The call
public void DeleteAfromAllB(Object a)
does not need to pass the SqlConnection as you can reference from tr.Connection. So you just need the SqlTransaction as parameter. So for your original question, yes I think passing in the SqlTransaction is the way to go. Personally I prefer this way because you can easily trace the call stack / scope of the transaction (i.e. where the transaction started/finished).
Another alternative is to use a TransactionScope.
E.g.
private void DeleteAfromAllB(Object a)
{
using (var con = new SqlConnection())
{
con.open();
using (var cmd = new SqlCommand("STP_B_Delete_Referenc_To_A", con))
{
// some parameters
// some sort of Execute
// e.g.: cmd.ExecuteNonQuery();
}
}
}
public void DeleteAfromAllB_TopLevel(Object a)
{
using (var scope = new TransactionScope())
{
try
{
DeleteAfromAllB(a);
// The Complete method commits the transaction. If an exception has been thrown,
// Complete is not called and the transaction is rolled back.
scope.Complete();
}
catch (Exception)
{
//ExceptionHandling
}
}
}
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);
}
}
}
}
private void button1_Click(object sender, EventArgs e)
{
try
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Data Source=*******;Initial Catalog=ChatApp;User ID=Chatapplication;Password=****";
conn.Open();
SqlCommand cmd = new SqlCommand();
string chatroomidno = textBox1.Text;
string chatroomname = textBox2.Text;
//cmd.CommandText = "Select ChatRoomID=#ChatRoomID,ChatRoomName=#ChatRoomName from tblChatRoom";
//cmd.Connection = conn;
SqlDataAdapter adapt = new SqlDataAdapter("Chatroomapp",conn);
adapt.SelectCommand.CommandType = CommandType.StoredProcedure;
DataSet ds=new DataSet();
DataTable dt = new DataTable();
adapt.SelectCommand.Parameters.Add(new SqlParameter("#ChatRoomID", SqlDbType.VarChar, 100));
adapt.SelectCommand.Parameters["#ChatRoomID"].Value = chatroomidno;
adapt.SelectCommand.Parameters.Add(new SqlParameter("#ChatRoomName", SqlDbType.VarChar, 50));
adapt.SelectCommand.Parameters["#ChatRoomName"].Value = chatroomname;
adapt.Fill(ds, "tblChatRoom");
if (dt.Rows.Count > 0)
{
MessageBox.Show("Connection Succedded");
}
else
{
MessageBox.Show("Connection Fails");
}
}
catch (Exception ex)
{
MessageBox.Show("Error", ex.Message);
}
}
While compiling the program I got only connection fails message box, in the database. I found correct, how to overcome the program to get the connection succeeded message box.
Well, you're filling the ds data set - but then you're checking the dt data table for presence of rows... that's never going to work, of course!
If you only need a single DataTable - just use and fill that data table alone - no need for the overhead of a DataSet. Also, put your SqlConnection and SqlCommand into using blocks like this:
using (SqlConnection conn = new SqlConnection("Data Source=*******;Initial Catalog=ChatApp;User ID=Chatapplication;Password=****"))
using (SqlCommand cmd = new SqlCommand("Chatroomapp", conn))
{
string chatroomidno = textBox1.Text;
string chatroomname = textBox2.Text;
SqlDataAdapter adapt = new SqlDataAdapter(cmd);
adapt.SelectCommand.CommandType = CommandType.StoredProcedure;
adapt.SelectCommand.Parameters.Add(new SqlParameter("#ChatRoomID", SqlDbType.VarChar, 100));
adapt.SelectCommand.Parameters["#ChatRoomID"].Value = chatroomidno;
adapt.SelectCommand.Parameters.Add(new SqlParameter("#ChatRoomName", SqlDbType.VarChar, 50));
adapt.SelectCommand.Parameters["#ChatRoomName"].Value = chatroomname;
// fill the data table - no need to explicitly call `conn.Open()` -
// the SqlDataAdapter automatically does this (and closes the connection, too)
DataTable dt = new DataTable();
adapt.Fill(dt);
if (dt.Rows.Count > 0)
{
MessageBox.Show("Connection Succedded");
}
else
{
MessageBox.Show("Connection Fails");
}
}
And just because you get back no rows in dt.Rows doesn't necessarily mean that your connection failed..... it could just be that there are no rows that match your search critieria! The connection worked just fine - but the SQL command just didn't return any rows.
Connection failed means that something went wrong between your program and the database. No records returned does not mean that the connection failed. It just means that your table is empty - it contains no records.
Using ADO.NET and a stored procedures would have been a little different from what you have done it. If you need to check if the connection failed, maybe it is better to check the type of exception that is returned in the catch part.
Below is how I would have done it. I would have created a separate method that would have handled my call, and then in your button1_Click I would have just called this method:
public async Task<ChatRoom> GetAsync(string chatRoomId, string chatRoomName)
{
try
{
string connectionString = ConfigurationManager.ConnectionStrings["Db"].ConnectionString;
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
await sqlConnection.OpenAsync();
using (SqlCommand sqlCommand = new SqlCommand("ChatRooms_Get", sqlConnection))
{
sqlCommand.CommandType = CommandType.StoredProcedure;
sqlCommand.Parameters.Add(new SqlParameter("#ChatRoomID", chatRoomId));
sqlCommand.Parameters.Add(new SqlParameter("#ChatRoomName", chatRoomName));
using (SqlDataReader sqlDataReader = await sqlCommand.ExecuteReaderAsync())
{
ChatRoom chatRoom = null;
if (await sqlDataReader.ReadAsync())
{
chatRoom = new ChatRoom();
chatRoom.Id = sqlDataReader.GetFieldValue<string>(0);
chatRoom.Name = sqlDataReader.GetFieldValue<string>(1);
chatRooms.Add(chatRoom);
}
return chatRoom;
}
}
}
}
catch (Exception exception)
{
// Try checking if the connection failed here
throw exception;
}
}
My chat room domain model could have looked like this:
public class ChatRoom
{
public string Id { get; set; }
public string Name { get; set; }
}
And the stored procedure would have looked like this:
CREATE PROCEDURE [dbo].[ChatRooms_Get]
(
#ChatRoomID VARCHAR(100),
#ChatRoomName VARCHAR(50)
)
AS
BEGIN
SET NOCOUNT ON;
SELECT
ChatRoomID,
ChatRoomName
FROM
tblChatRoom
WHERE
ChatRoomID = #ChatRoomID
AND ChatRoomName = #ChatRoomName;
END
GO
And then in the calling method you would get the chatroom and do with it whatever you need to do with it. For this example I just checked if it exists or not:
try
{
ChatRoom chatRoom = await chatRoomRepository.GetAsync(chatRoomId, chatRoomName);
if (chatRoom != null)
{
MessageBox.Show("Record found");
}
else
{
MessageBox.Show("No record found");
}
}
catch (Exception exception)
{
throw exception;
}
I hope this can help.
im facing a problem , when i creat my own class i want to create Mysql connection function and i want to use it inside all my forms i do this
program.cs
using MySql.Data.MySqlClient;
using MySql.Data.Types;
using System.Xml;
using System.IO;
public class testing
{
public string fahadt="Hello Class";
public void conncting()
{
MySqlConnection connection;
string cs = #"server=localhost;userid=root;password=;database=taxi";
connection = new MySqlConnection(cs);
try
{
connection.Open();
}
catch (MySqlException ex)
{
// MessageBox.Show(ex.ToString());
}
}
}
and in my form
private void button7_Click(object sender, EventArgs e)
{
testing fahad = new testing();
try
{
dataGridView1.Show();
fahad.conncting();
// here is error under fahad.conncting.createcommand();
MySqlCommand cmd = fahad.conncting.CreateCommand();
//cmd.CommandText = "SELECT * FROM ocms_visitors WHERE `id`='"+textBox4.Text+"'";
// MySqlDataAdapter adap = new MySqlDataAdapter(cmd);
//textBox4.Text = adap.id;
// DataSet ds = new DataSet();
// adap.Fill(ds);
// dataGridView1.DataSource = ds.Tables[0].DefaultView;
//MessageBox.Show("Yes Mysql Connection is Working Now !");
}
catch (Exception)
{
throw;
}
}
i dont know how i can do it im very new = C#
please help me and also i have another q should i use
using .... in class and form or Enough in class ?
thanks
You need to return MySqlConnection
Modify your function to:
public MySqlConnection conncting()
{
MySqlConnection connection;
string cs = #"server=localhost;userid=root;password=;database=taxi";
connection = new MySqlConnection(cs);
try
{
connection.Open();
return connection;
}
catch (MySqlException ex)
{
return null;
// MessageBox.Show(ex.ToString());
}
}
To answer your initial question, it looks to me like you have already created the connection you were looking for. Next steps for you would be to learn about the SqlCommand Class.
For reference/edification, try this link, and happy coding!
I suspect you want to return a connection from your conncting() method?
public MySqlConnection conncting()
{
string cs = #"server=localhost;userid=root;password=;database=taxi";
MySqlConnection connection = new MySqlConnection(cs);
connection.Open();
return connection;
}
To answer your second question, yes, using using {..} blocks is a good idea for IDisposable instances whenever possible. This includes connections, commands, data adapters, etc. The following might be a reasonable pattern:
using (MySqlConnection conn = fahad.conncting())
using (MySqlCommand cmd = new MySqlCommand("select * from table", conn))
using (MySqlDataAdapter da = new MySqlDataAdapter(cmd))
using (DataTable dt = new DataTable())
{
da.Fill(dt);
// do something with datatable
}