Programming Practice: Using ExecuteNonQuery with SqlDataAdapter - c#

public DataTable UserUpdateTempSettings(int install_id, int install_map_id, string Setting_value,string LogFile)
{
SqlConnection oConnection = new SqlConnection(sConnectionString);
DataSet oDataset = new DataSet();
DataTable oDatatable = new DataTable();
SqlDataAdapter MyDataAdapter = new SqlDataAdapter();
try
{
oConnection.Open();
cmd = new SqlCommand("SP_HOTDOC_PRINTTEMPLATE_PERMISSION", oConnection);
cmd.Parameters.Add(new SqlParameter ("#INSTALL_ID", install_id));
cmd.Parameters.Add(new SqlParameter ("#INSTALL_MAP_ID", install_map_id));
cmd.Parameters.Add(new SqlParameter("#SETTING_VALUE", Setting_value));
if (LogFile != "")
{
cmd.Parameters.Add(new SqlParameter("#LOGFILE",LogFile));
}
cmd.CommandType = CommandType.StoredProcedure;
MyDataAdapter.SelectCommand = cmd;
cmd.ExecuteNonQuery();
MyDataAdapter.Fill(oDataset);
oDatatable = oDataset.Tables[0];
return oDatatable;
}
catch (Exception ex)
{
Utils.ShowError(ex.Message);
return oDatatable;
}
finally
{
if ((oConnection.State != ConnectionState.Closed) || (oConnection.State != ConnectionState.Broken))
{
oConnection.Close();
}
oDataset = null;
oDatatable = null;
oConnection.Dispose();
oConnection = null;
}
}
I have used ExecuteNonQuery above. Normally it's not used with SqlDataAdapter. If I do not use it, I get an error.
Is it bad programming practice to use ExecuteNonQuery with SqlDataAdapter?

Hi deepti you don't have to call executeNonQuery because the fill method of the dataadapter is taking care for you. Here is a small sample:
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
namespace WindowsFormsApplication9
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
FillData();
}
void FillData()
{
// 1
// Open connection
using (SqlConnection c = new SqlConnection(
Properties.Settings.Default.DataConnectionString))
// 2
// Create new DataAdapter
using (SqlDataAdapter a = new SqlDataAdapter("SELECT * FROM EmployeeIDs", c))
{
// 3
// Use DataAdapter to fill DataTable
DataTable t = new DataTable();
a.Fill(t);
// 4
// Render data onto the screen
// dataGridView1.DataSource = t; // <-- From your designer
}
}
}
}

I don't think it's a matter of bad practice, it just doesn't make sense to do it in this situation. The fill method is used to populate the results from a select command. ExecuteNonQuery() is normally used when you're not retrieving data, and will only return the number of results.
You can find more about the fill method here

Related

DataTable returns null WPF

I want to display data in a datagrid based on value selected in a ComboBox but my datatable function returns null and nothing is displayed in the datagrid.
public DataTable ReadData(User user)
{
using (SqlConnection db = new SqlConnection(AppConnect.Connection))
{
string query = "SELECT moduleCode,moduleName,modCredits,modHrsLeft FROM [Module] WHERE userName=#userName";
try
{
using (SqlCommand command = new SqlCommand(query, db))
{
if (db.State == ConnectionState.Closed)
{
db.Open();
command.Parameters.AddWithValue("#userName", user.UserName);
SqlDataAdapter dataAdapter = new SqlDataAdapter(command);
table = new DataTable();
dataAdapter.Fill(table);
}
}
db.Close();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return table;
}
}
This function is in a class library. The function is called in the WPF project, this is the code:
private void BtnDisplay_Click(object sender, RoutedEventArgs e)
{
string userName = CmboxUserN.SelectedItem.ToString();
User user1 = new User
{
UserName = userName
};
DataTable table = data.ReadData(user1);
gridModules.DataContext= table;
}
Try these changes. It seems that the line table = new DataTable(); is never being hit. You don't need to check to make sure the connection is in a closed state because you are using a using statement.
public DataTable ReadData(User user)
{
using (SqlConnection db = new SqlConnection(AppConnect.Connection))
{
string query = "SELECT moduleCode,moduleName,modCredits,modHrsLeft FROM [Module] WHERE userName=#userName";
try
{
using (SqlCommand command = new SqlCommand(query, db))
{
db.Open();
command.Parameters.AddWithValue("#userName", user.UserName);
SqlDataAdapter dataAdapter = new SqlDataAdapter(command);
table = new DataTable();
dataAdapter.Fill(table);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return table;
}
}
Also, you don't need to .Close() the connection because the SqlConnection is in a using statement, which means the object will be disposed of when the scope of the using statement is exited.
One other tip: You should change the code to have the try catch around everyting and if there are any errors at all, log the errors to console and return a new DataTable().

SqlHelper DataAdapter

I am using a SqlHelper class which has common methods for CRUD operations.
public static void Fill(DataSet dataSet, String procedureName)
{
SqlConnection oConnection = new SqlConnection(DBInterface.ConnectionString);
SqlCommand oCommand = new SqlCommand(procedureName, oConnection);
oCommand.CommandType = CommandType.StoredProcedure;
SqlDataAdapter oAdapter = new SqlDataAdapter();
oAdapter.SelectCommand = oCommand;
oConnection.Open();
using (SqlTransaction oTransaction = oConnection.BeginTransaction())
{
try
{
oAdapter.SelectCommand.Transaction = oTransaction;
oAdapter.Fill(dataSet);
oTransaction.Commit();
}
catch
{
oTransaction.Rollback();
throw;
}
finally
{
if (oConnection.State == ConnectionState.Open)
oConnection.Close();
oConnection.Dispose();
oAdapter.Dispose();
}
}
}
Now in my code, I am calling this method as,
private void BindCustomers()
{
DataSet dsCust = new DataSet();
SqlHelper.Fill(dsCust, "getCustomers");
--then I bind this dataset to datagridview
}
This all works fine. Now I want to update the data in the database. But I am confused how do I call DataAdatpaer.Update(dataset) here to update the changes made in datagridview into database. Is this possible here? Or I need to do it conventionally to find the updated row and call the ExecuteNonQuery function in the SqlHelper? Is there anything which can be done to use dataadapter.update(ds)
Thanks
You don't need to hide data adapter, or if for any reason you did so, you need to expose a method in your class to push updates to server.
Example
Public class SqlHelper
{
string commandText;
string connectionString;
public SqlHelper(string command, string connection)
{
commandText = command;
connectionString = connection;
}
public DataTable Select()
{
var table = new DataTable();
using (var adapter = new SqlDataAdapter(this.commandText, this.connectionString))
adapter.Fill(table)
return table;
}
public void Update(DataTable table)
{
using (var adapter = new SqlDataAdapter(this.commandText, this.connectionString))
{
var builder = new SqlCommandBuilder(adapter);
adapter.Update(table);
}
}
}
By calling this method in your code you can perform all crud operation select, update, delete and insert. you just need to pass connection string, procedure name and parameters list. Using this method you will retrieve data in the DataTable.if anyone want Dataset(Multiple Result) then just need to replace DataSet on the place of DataTable
SqlConnection conn = new SqlConnection("Your ConnectionString");
public DataTable ExecuteDataTable(string ProcedureName, SqlParameter[] _Param)
{
try
{
DataTable dataTable = new DataTable();
SqlCommand cmd = new SqlCommand(ProcedureName, conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Clear();
if (_Param is not null)
{
for (int i = 0; i < _Param.Length; i++)
{
if (_Param[i].ParameterName is not null)
{
if (_Param[i].Value is not null)
{
cmd.Parameters.AddWithValue(_Param[i].ParameterName, _Param[i].Value);
}
else
{
cmd.Parameters.AddWithValue(_Param[i].ParameterName, DBNull.Value);
}
}
}
}
conn.Open();
SqlDataAdapter DA = new SqlDataAdapter(cmd);
DA.Fill(dataTable);
conn.Close();
return dataTable;
}
catch (Exception ex)
{
conn.Close();
throw;
}
}

How to call a stored procedure using ADO.NET?

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.

Is it safe to use static methods for accessing database in following scenario

I am upgrading a asp website to asp.net. I am trying to follow multi teir approach.
My basic dal layer is as follows which returns a datatable and insert a given query.
using System;
using System.Configuration;
using System.Data;
using MySql.Data.MySqlClient;
public class mydatautility
{
public mydatautility()
{
}
public static DataTable Table(string query)
{
string constr = ConfigurationManager.ConnectionStrings["db_con"].ConnectionString;
DataTable table = new DataTable();
try
{
using (MySqlConnection con = new MySqlConnection(constr))
{
con.Close();
MySqlCommand com = new MySqlCommand(query, con);
MySqlDataAdapter da = new MySqlDataAdapter(com);
con.Open();
da.Fill(table);
con.Close();
da = null;
com = null;
con.Dispose();
}
}
catch (Exception)
{
}
return table;
}
public static int Insert_intoemployee(string query)
{
string constr = ConfigurationManager.ConnectionStrings["db_con"].ConnectionString;
int done = 0;
try
{
using (MySqlConnection con = new MySqlConnection(constr))
{
MySqlCommand com = new MySqlCommand(query, con);
con.Open();
done = com.ExecuteNonQuery();
con.Close();
com = null;
con.Dispose();
}
}
catch (Exception)
{
}
return done;
}
}
I am not sure what will happen when 2 concurrent queries are run.How can I test it for concurrency problem?
There will no concurrency problem as each request has its own thread and static methods have individual call stacks for each thread. However, there are some suggestions in code.
using System;
using System.Configuration;
using System.Data;
using MySql.Data.MySqlClient;
public static class mydatautility//change to Utilities
{
public mydatautility()//not required in this scenario
{
}
public static DataTable Table(string query) //change method name to GetTable
{
string constr = ConfigurationManager.ConnectionStrings["db_con"].ConnectionString;
DataTable table = new DataTable();
try
{
using (MySqlConnection con = new MySqlConnection(constr))
{
con.Close();//not required
using(MySqlCommand com = new MySqlCommand(query, con))
{
MySqlDataAdapter da = new MySqlDataAdapter(com);
con.Open();
da.Fill(table);
con.Close();
da = null;// reduntant, not required
com = null;// reduntant, not required
con.Dispose();// reduntant, not required
}
}
}
catch (Exception)
{
}
return table;
}
public static bool InsertEmployee(string query)// consider changing int to bool since you only require result of operation
{
string constr = ConfigurationManager.ConnectionStrings["db_con"].ConnectionString;
int done = 0;
try
{
using (MySqlConnection con = new MySqlConnection(constr))
{
Using(MySqlCommand com = new MySqlCommand(query, con))
{
con.Open();
done = com.ExecuteNonQuery();
con.Close();
com = null;// reduntant, not required
con.Dispose();// reduntant, not required
}
}
}
catch (Exception)
{
}
return done > 0; // checks rows affected greater than 0
}
}
Using static methods in this scenario is safe. The variables inside the static method is isolated from concurrent calls! see this link too: variable in static methods inside static class
I think it is safe, but bad practice. If you use static methods to access live resource, then how do you want to unit test them? You can not really mock the database access any more.

c sharp return object from function

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
}

Categories