Retrieving a Row from a table causes invalid column name error - c#

I am trying to delete a record in my database table. I am trying to delete it on the basis of a selected name in the dropdown list. When I debug my code there is not any record available in dataset and an exception "invalid column name" occurs, whereas if I run the same query in SQL Server, everything seems to be fine.
This is my code:
protected void SubCategory_Delete_Click(object sender, EventArgs e)
{
try
{
var conn = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\template_castle.mdf;Integrated Security=True");
var adpt = new SqlDataAdapter("Select * from tc_prod_subcategory where subcategory_name = ' ' "+ DropDownList2.SelectedItem.Value, conn);
var ds = new DataSet();
adpt.Fill(ds, "tc_prod_subcategory");
foreach (DataRow dr in ds.Tables["tc_prod_subcategory"].Rows)
{
dr.Delete();
}
SqlCommandBuilder build = new SqlCommandBuilder(adpt);
adpt.Update(ds, "tc_prod_subcategory");
Updatesubcategorygrid();
updatedelete_dropdown();
Lblsub_catdelete.Text = "Deleted Successfully";
}
catch(Exception ex)
{
Lblsub_catdelete.Text = ex.Message;
}
}
And this is the same query when I run it in SQL Server 2014; everything runs fine:
Select *
from tc_prod_subcategory
Where subcategory_name= 'Favicon'

The error is caused by the incorrect position of the apostophes in the where clause. It should be like:
"Select * from tc_prod_subcategory where subcategory_name = '" + DropDownList2.SelectedItem.Value + "'"
but that code is vulnerable to a SQL injection,so you should use parameters instead of concatenating strings.
var conn = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\template_castle.mdf;Integrated Security=True");
var adpt = new SqlDataAdapter("Select * from tc_prod_subcategory where subcategory_name = #subcategory_name", conn);
var ds = new DataSet();
adpt.SelectCommand.Parameters.AddWithValue("#subcategory_name", DropDownList2.SelectedItem.Value);

If you use c# version >= 6.0
you can use interpolation to concat strings in very handy and less error-prone way.
var adpt = new SqlDataAdapter($"Select * from tc_prod_subcategory where subcategory_name = '{DropDownList2.SelectedItem.Value}'", conn);

Related

An unhandled exception when try to input data to MySQL Table

I'm new in learning C# and MySql using Visual Basic Community 2015, I'm trying to make simple CRUD, but I'm confused when I Run the Program and try to input data to MySql Table because it always shows message
An unhandled exception of type 'MySql.Data.MySqlClient.MySqlException' occurred in MySql.Data.dll
Additional information:
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'Siswa,Total Biaya SPP,Sisa Bayar SPP,Keterangan) VALUES
is there any solution for this?
public partial class Crud : Form
{
MySqlConnection conn = new MySqlConnection("Server=localhost;User Id=root;Password='';Database=db_csharp1");
MySqlDataAdapter adapter = new MySqlDataAdapter();
MySqlCommand command = new MySqlCommand();
public DataSet ds = new DataSet();
public Crud()
{
InitializeComponent();
}
private void Crud_Load(object sender, EventArgs e)
{
GetRecords();
}
private void btnTambah_Click(object sender, EventArgs e)
{
ds = new DataSet();
adapter = new MySqlDataAdapter ("INSERT INTO siswa (NIS,Nama Siswa,Total Biaya SPP,Sisa Bayar SPP,Keterangan) VALUES ('"+textNIS.Text+"','"+textNamaSiswa.Text+"','"+textBiayaSPP.Text+"','"+textSisaBayar.Text+"','"+textKeterangan+"')", conn);
adapter.Fill(ds,"siswa");
MessageBox.Show("Added!");
textNIS.Clear();
textNamaSiswa.Clear();
textBiayaSPP.Clear();
textSisaBayar.Clear();
textKeterangan.Clear();
GetRecords();
}
private void GetRecords()
{
ds = new DataSet();
adapter = new MySqlDataAdapter("select * from siswa", conn);
adapter.Fill(ds, "siswa");
dataGridView1.DataSource = ds;
dataGridView1.DataMember = "siswa";
}
You have spaces in your column names. Use ` in your column names.
INSERT INTO siswa (`NIS`,`Nama Siswa`,`Total Biaya SPP`,`Sisa Bayar SPP`,`Keterangan`)
In your case, you can use Parametrized query to fill your Dataset. Now since the string used to initialize the SqlDataAdapter becomes the CommandText of the SelectCommand property of the SqlDataAdapter. So you can add your parameters like this:
adapter = new MySqlDataAdapter ("INSERT INTO siswa (`NIS`,`Nama Siswa`,`Total Biaya SPP`,`Sisa Bayar SPP`,`Keterangan`) VALUES (#textNIS,#textNamaSiswa,#textBiayaSPP,#textSisaBayar,#textKeterangan)", conn);
adapter.SelectCommand.Parameters.AddWithValue("#textNIS","%" + textNIS.Text + "%");
adapter.SelectCommand.Parameters.AddWithValue("#textNamaSiswa","%" + textNamaSiswa.Text + "%");
adapter.SelectCommand.Parameters.AddWithValue("#textBiayaSPP","%" + textBiayaSPP.Text + "%");
adapter.SelectCommand.Parameters.AddWithValue("#textSisaBayar","%" + textSisaBayar.Text + "%");
adapter.SelectCommand.Parameters.AddWithValue("#textKeterangan","%" + textKeterangan + "%");
Not sure if your field textKeterangan value should be textKeterangan.Text or textKeterangan. You can take care of this.

SQL Values to integers

I'm trying to compare values in a database that are updated every time a user logs in. When I execute a query with the given code nothing happens. However if I give it a value of say (where Attempt >10) it works where am I going wrong?
private void User_Tick(object sender, EventArgs e)
{
SqlConnection con13 = new SqlConnection("Data Source = *** ")
SqlDataAdapter SDA2 = new SqlDataAdapter("SELECT [User],[Login],[number1],[number2],[number3],[Alertcount] FROM Users.dbo.[Email] where [Alertcount] = 1 and [Alertcount] !=2", con13);
DataTable Users = new DataTable();
DataTable DATA2 = new DataTable();
SDA2.Fill(DATA2);
dataGridView2.DataSource = DATA2;
foreach (DataGridViewRow dr in dataGridView2.Rows)
{
string col2 = 1.Cells["User"].Value.ToString();
string col1 = 1.Cells["Login"].Value.ToString();
string col3 = 1.Cells["number1"].Value.ToString();
string col4 = 1.Cells["number2"].Value.ToString();
string col5 = 1.Cells["number3"].Value.ToString();
string col6 = 1.Cells["Alertcount"].Value.ToString();
var mine = Convert.ToInt32(col3);
var mine2 = Convert.ToInt32(col5);
SqlConnection CON2 = new SqlConnection("Data Source = ***")
CON2.Open();
SqlDataAdapter SDA = new SqlDataAdapter("SELECT [User],[Login],[Attempt] FROM User.dbo.Actions where [Attempt] > '"+mine+ "' and [Attempt] < '" + mine2 + "'", CON2);
DataTable DATA = new DataTable();
SDA.Fill(DATA);
dataGridView1.DataSource = DATA;
}
}
If column Attempt is an integer (as evident from the fact that Attempt < 10 runs), you need not pass comparison values to it in string. So your query should be like this:
SqlDataAdapter SDA = new SqlDataAdapter("SELECT [User],[Login],[Attempt] FROM User.dbo.Actions where [Attempt] > "+mine+ " and [Attempt] < " + mine2 , CON2);
I would suggest you to debug such errors in future by creating a query variable and then running the query in SQL manually to see what the error is. You could do something like this:
var query = "SELECT [User],[Login],[Attempt] FROM User.dbo.Actions where [Attempt] > "+mine+ " and [Attempt] < " + mine2 ;
SqlDataAdapter SDA = new SqlDataAdapter(query , CON2);
nothing happens - not enough information for correct answer. If actually nothing happens, then remove all try catch blocks you have around code and run application again. Then if something wrong you will get very useful information about what gone wrong in the form of Exception.
However, problem seems is that you passing wrong data to database query.
Always use SqlParameter for passing dynamic data to the query. SqlParameter have type which you can set to correspondent type of column you want operate on. Also SqlParameter will protect you from sql injection.
Use using for disposable objects when ever it possible (read "always")
var emailQuery =
#"SELECT [User] ,[Login] ,[number1] ,[number2] ,[number3] ,[Alertcount]
FROM Users.dbo.[Email]
WHERE [Alertcount] = 1
AND [Alertcount] !=2"; // Useless condition, because Alertcount already = 1
using(var connection2 = new SqlConnection("Data Source = *** "))
using(var adapter2 = new SqlDataAdapter(emailQuery, connection1))
{
var data2 = new DataTable();
adapter2.Fill(data2);
dataGridView2.DataSource = data2;
}
var actionsQuery =
#"SELECT [User] ,[Login] ,[Attempt]
FROM User.dbo.Actions
WHERE Attempt > #Mine AND Attempt < #Mine2";
foreach (var row in dataGridView2.Rows)
{
var mine = (int)row.Cells["number1"].Value; // it is already integer, just cast it
var mine2 = (int)row.Cells["number3"].Value;
using(var connection1 = new SqlConnection("Data Source = *** "))
using(var adapter1 = new SqlDataAdapter(actionsQuery, connection1))
{
var parameters = new[]
{
new SqlParameter
{
ParameterName = "#Mine",
SqlDbType = SqlDbType.Int,
Value = mine
},
new SqlParameter
{
ParameterName = "#Mine2",
SqlDbType = SqlDbType.Int,
Value = mine2
}
};
adapter1.SelectCommand.Parameters.AddRange(parameters);
var data1 = new DataTable();
adapter.Fill(data1);
dataGridView1.DataSource = data1
}
}

How to use openquery in c#

I have an openquery SQL script:
Select * from openquery([oak],'
SELECT LicenseKey, SUM(PaymentAmount)as Payments
FROM vw_ODBC_actv_Payments pt
WHERE MONTH(pt.EntryDate) = 2 and
YEAR(pt.EntryDate) = 2015
GROUP BY LicenseKey
')
When I run this from SSMS I can see that it returns expected n rows.
However when I'm firing this with the same connection properties to get the data in a DataSet for a C# console application:
SqlDataAdapter da = new SqlDataAdapter();
SqlCommand pcmd= new SqlCommand();
DataSet ds= new DataSet();
OpenConnection();
pcmd.Connection = new SqlConnection("Data source=IP adress of the server;Initial Catalog=master; user ID=***; password=***");
cmd.CommandText = "Select * from openquery([oak],'" +
"SELECT LicenseKey, SUM(PaymentAmount)as Payments" +
"FROM vw_ODBC_actv_Payments pt " +
"WHERE MONTH(pt.EntryDate) = 2 and" +
"YEAR(pt.EntryDate) = 2015" +
"GROUP BY LicenseKey')";
try
{
da.SelectCommand = pcmd;
da.Fill(ds); //here comes the error
}
catch (Exception ex)
{
throw new Exception("DBUtils.ExecuteReader():" + ex.Message);
}
I'm getting an error like this:
The provider indicates that the user did not have the permission to
perform the operation. Now I need to do something with this issue
I'm just learning about openquery. Can anybody guide?
Firstly you're not opening the connection anywhere in your code hence the error. Second clean up your code with the using block. So assuming the query works as required you can do something like.
using(SqlConnection con = new SqlConnection("Connection String Here"))
{
string myQuery = "Your Query";
using(SqlCommand cmd = new SqlCommand(myQuery, con))
{
using (SqlDataAdapter sda = new SqlDataAdapter())
{
con.Open();
sda.SelectCommand = cmd;
DataSet ds = new DataSet();
sda.Fill(ds);
}
}
}
Note: It would be a better if you stored the connectionString in your config file and read it in your code.

Unable to update database in ASP.NET

I wanted to update a record to the database but it just keep reverting to its original value.
Below is my code. No error was display to me either.
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["CandidateConnectionString"].ConnectionString);
conn.Open();
string updateData = "UPDATE Resume SET [Work_Experience] = #work_exp, [Educational_Level] = #edu_level, [Field_Of_Study] = #field_study, [University_Name] = #uni_name, [University_Location] = #uni_locate, [Graduation_Year] = #gra_year WHERE Cand_ID = (SELECT Cand_ID FROM Candidate WHERE Cand_Username = '"+ usernamelbl.Text +"')";
SqlCommand cmd = new SqlCommand(updateData, conn);
cmd.Parameters.AddWithValue("#work_exp", Work_Exp.Text);
cmd.Parameters.AddWithValue("#edu_level", Edu_Level.SelectedItem.Text);
cmd.Parameters.AddWithValue("#field_study", Field_Study.SelectedItem.Text);
cmd.Parameters.AddWithValue("#uni_name", Uni_Name.Text);
cmd.Parameters.AddWithValue("#uni_locate", Uni_Locate.Text);
cmd.Parameters.AddWithValue("#gra_year", Year.Text);
cmd.ExecuteNonQuery();
conn.Close();
Any Problem with the code?
I just found out a stupid mistake..
On the page_Load event, I have a line of code which is fetching value from the database
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["CandidateConnectionString"].ConnectionString);
conn.Open();
string getdata = "SELECT * FROM Resume WHERE Cand_ID = (SELECT Cand_ID FROM Candidate WHERE Cand_Username = '" + usernamelbl.Text + "')";
SqlCommand com = new SqlCommand(getdata, conn);
SqlDataAdapter sda = new SqlDataAdapter(com);
DataSet ds = new DataSet();
sda.Fill(ds, "Resume");
Work_Exp.Text = ds.Tables["Resume"].Rows[0]["Work_Experience"].ToString();
Edu_Level.Text = ds.Tables["Resume"].Rows[0]["Educational_Level"].ToString();
Field_Study.Text = ds.Tables["Resume"].Rows[0]["Field_Of_Study"].ToString();
Uni_Name.Text = ds.Tables["Resume"].Rows[0]["University_Name"].ToString();
Uni_Locate.Text = ds.Tables["Resume"].Rows[0]["University_Location"].ToString();
Year.Text = ds.Tables["Resume"].Rows[0]["Graduation_Year"].ToString();
conn.Close();
But I didn't include it under if(!IsPostBack) and that's the reason whenever I submit, it overwrites my current value and revert it back to the original state. Thanks to you guys who trying to help me sort out and teaches me about new stuff. :)

Get records between two days which are selected by two datetimepickers and fill a datagridview with them in Visual Studio C#

This is my code:
This is in a different class named DBAccess
public DataSet getRecords(DateTime dtpFloor,DateTime dtpCeiling)
{
if (conn.State.ToString() == "Closed")
{
conn.Open();
}
SqlCommand newCmd = conn.CreateCommand();
newCmd.Connection = conn;
newCmd.CommandType = CommandType.Text;
newCmd.CommandText = " SELECT * FROM dbo.ClientInvoice WHERE invDate BETWEEN '" + dtpCeiling + "' AND '" + dtpFloor + "'";
SqlDataAdapter da = new SqlDataAdapter(newCmd);
DataSet dsIncome = new DataSet();
da.Fill(dsIncome, "Client");
conn.Close();
return dsIncome;
}
Below Coding is in the ProfitLos form class
public void btnClickFillGrid()
{
DataSet dsIncome = dba.getRecords(dtpFloor.Value.ToString(), dtpCeiling.Value.ToString()); //dba is an object of DBAccess class
dgvproIncome.DataSource = dsIncome.Tables["Client"].DefaultView;
}
btnClickFillGrid() will invoke at the button click event.
In the database - invdate datetime;(invDate is the variable name and its in the datetime format)
i edited my coding like this
public DataSet getRecords(DateTime dtpFloor,DateTime dtpCeiling)
{
using (SqlConnection conn = new SqlConnection("Data Source=KOSHITHA-PC;Initial Catalog=ITP;Integrated Security=True"))
{
conn.Open();
using (SqlCommand command = conn.CreateCommand())
{
string sql = "SELECT * FROM dbo.ClientInvoice WHERE invDate BETWEEN" + "#from AND #to";
command.CommandText = sql;
command.Parameters.AddWithValue("#from",dtpFloor);
command.Parameters.AddWithValue("#to", dtpCeiling);
SqlDataAdapter da = new SqlDataAdapter(command);
DataSet dataSetClient = new DataSet();
da.Fill(dataSetClient, "Client");
return dataSetClient;
}
}
}
DataSet dataSetClient = dba.getRecords(dtpFloor.Value, dtpCeiling.Value);
dgvproIncome.DataSource = dataSetClient.Tables["Client"].DefaultView;
now i m getting an exception in "da.Fill(dataSetClient, "Client");" line saying
sqlException was unhandled
An expression of non-boolean type specified in a context where a condition is expected, near 'BETWEEN#from'.
i m not familiar with the parameter passing method to sql query,so couldnt find the problem that i m having
Look at this call:
dba.getRecords(dtpFloor.Value.ToString(), dtpCeiling.Value.ToString());
That's clearly passing in strings as the arguments. Now look at your method declaration:
public DataSet getRecords(DateTime dtpFloor,DateTime dtpCeiling)
Those parameters are of type DateTime, not string. So the first thing to fix is the call, to:
dba.getRecords(dtpFloor.Value, dtpCeiling.Value);
Now the next problem is that you're embedding the values in the SQL directly. Don't do that. Never do that. In some cases it can lead to SQL injection attacks, and in other cases it causes data conversion issues (as you've got here). Use parameterized SQL instead - oh, and use connection pooling rather than trying to use a single connection in multiple places:
public DataSet GetRecords(DateTime dtpFloor,DateTime dtpCeiling)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand command = conn.CreateCommand())
{
string sql = "SELECT * FROM dbo.ClientInvoice WHERE invDate BETWEEN "
+ "#from AND #to";
command.CommandText = sql;
command.Parameters.AddWithValue("#from", dtpFloor");
command.Parameters.AddWithValue("#to", dtpCeiling");
SqlDataAdapter da = new SqlDataAdapter(command);
DataSet dataSet = new DataSet();
da.Fill(dataSet, "Client");
return dataSet;
}
}
}

Categories