C# variable in a MySql query isn't recognized - c#

I have an int variable in my C# code and I'm trying to use it in a MySql query.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MySql.Data;
using MySql.Data.MySqlClient;
namespace projeV1
{
public partial class ProjeDetay : Form
{
public ProjeDetay()
{
InitializeComponent();
}
private void ProjeDetay_Load(object sender, EventArgs e)
{
int satir_projem = Projeler.satir_proje;
string connectionString = "Server = localhost; Port = ...; Database = ...; Uid = root; Pwd = ...; Allow User Variables=True";
MySqlConnection databaseConnection = new MySqlConnection(connectionString);
MySqlCommand command;
databaseConnection.Open();
command = databaseConnection.CreateCommand();
string myQuery = "select projeAdi from projeler where projeID = #satir_projem";
MySqlDataAdapter dataAdapter = new MySqlDataAdapter(myQuery, databaseConnection);
command.Parameters.Add("#satir_projem", MySqlDbType.Int32).Value = satir_projem;
DataSet DS = new DataSet();
dataAdapter.Fill(DS);
dataGridView_ProjeDetay.DataSource = DS.Tables[0];
MessageBox.Show(Projeler.satir_proje.ToString());
MessageBox.Show(satir_projem.ToString());
}
}
}
(Sorry if it looks like a mess in regard to coding but I'm new at this ^^)
MessageBox windows show the variables' values correctly, so there's no problem with the variable. And when I replace#satir_projem from the query string with a number like "2" (see the example below), for example, the result is correct, but when I use #satir_projem in the query, it doesn't work. I can't see what I'm doing wrong.
Example query string:
"select projeAdi from projeler where projeID = 2"
P.S 1: Originally I'm trying to get the index of the selected row (which is the variable called Projeler.satir_proje) in a DataGridView used in a form called "Projeler" and in another form (which is called ProjeDetay), assigning that index value into another variable called "satir_projem" and use this value to get the related data from my database and put that data in another DataGridView located in my second form (which is called dataGridView_ProjeDetay).
P.S 2: I've made a lot of research about this problem and tried many of the solutions I encountered along the way; however, none of them worked for me. So, here I am :)
Thanks in advance.

You are setting parameter for command that is not used.
Instead you should use DataAdapter.SelectCommand
dataAdapter.SelectCommand.Parameters.Add(...)

MySqlConnection databaseConnection = new MySqlConnection(connectionString);
MySqlCommand command;
string myQuery = "select projeAdi from projeler where projeID = #satir_projem";
databaseConnection.Open();
command = new MySqlCommand(myQuery, databaseConnection);
MySqlDataAdapter dataAdapter = new MySqlDataAdapter(command);

Just want to elaborate, why #Onur_Saatcioglu's code is throwing error.
you are adding #satir_projem to command but the parameter thus added to command is not being passed to dataadapter which serves as a bridge between a DataSet and SQL Server for retrieving and saving data.
Hence you can
1) As Lester told, create command like
command = new MySqlCommand(myQuery, databaseConnection);
and pass the command to DataAdapter
MySqlDataAdapter dataAdapter = new MySqlDataAdapter(command);
2) As #Pablo_notPicasso said, if you are using
dataAdapter.SelectCommand.Parameters.AddWithValue("#satir_projem", satir_projem);
then "command" does not make sense, you can just delete it.

Related

Try statement not executing - goes straight to catch

I am setting up a winform that takes the first name, last name, and student ID of a student into an sql database named college, and performs a stored procedure which searches for that student, then displays the results in a DataGridView when the search button is pressed. Whenever I press the search button I get the following error
"A first chance exception of type 'System.TypeInitializationException' occurred in Search2.exe".
My program is skipping over the Try block shown, and going to the Catch statement. Can anyone tell me why this is?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Search2
{
public partial class frmSearch : Form
{
public frmSearch()
{
InitializeComponent();
}
private void btnSearch_Click(object sender, EventArgs e)
{
string studid, fname, lname;
try
{
// get the values
fname = txtFname.Text.Trim();
lname = TxtLname.Text.Trim();
studid = txtStudentID.Text.Trim();
//instantiate datatier
Class1 astudent = new Class1();
DataSet ds = new DataSet();
ds = astudent.GetStudents(studid, fname, lname);
// populate the datagrid with dataset
dgvStudents.DataSource = ds.Tables[0];
}
catch (Exception ex)
{
}
}
private void frmSearch_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'collegeDataSet.STUDENT' table. You can move, or remove it, as needed.
//this.sTUDENTTableAdapter.Fill(this.collegeDataSet.STUDENT);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualBasic;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Data.SqlClient;
using System.Globalization;
namespace Search2
{
class Class1: frmSearch
{
static String connString = ConfigurationManager.ConnectionStrings["Data Source=EVEDELL17;Initial Catalog=College;Integrated Security=True"].ConnectionString;
static SqlConnection myConn = new SqlConnection(connString);
static System.Data.SqlClient.SqlCommand cmdString = new System.Data.SqlClient.SqlCommand();
public DataSet GetStudents(string studid, string fname, string lname)
{
try
{
// Open Connection
myConn.Open();
//clear command argument
cmdString.Parameters.Clear();
//command
cmdString.Connection = myConn;
cmdString.CommandType = CommandType.StoredProcedure;
cmdString.CommandTimeout = 1500;
cmdString.CommandText = "SearchStudent";
// define input parameter
cmdString.Parameters.Add("#fname", SqlDbType.VarChar, 1).Value = fname;
cmdString.Parameters.Add("#lname", SqlDbType.VarChar, 25).Value = lname;
// adapter and daraset
SqlDataAdapter aAdapter = new SqlDataAdapter();
aAdapter.SelectCommand = cmdString;
DataSet aDataSet = new DataSet();
// fill adapter
aAdapter.Fill(aDataSet);
//return Dataset
return aDataSet;
}
catch (Exception ex)
{
throw new ArgumentException(ex.Message);
}
finally
{
myConn.Close();
}
}
}
}
Judging by the exception type--TypeInitializationException--I suspect the problem is with the static field initializers:
static String connString = ConfigurationManager.ConnectionStrings["Data Source=EVEDELL17;Initial Catalog=College;Integrated Security=True"].ConnectionString;
static SqlConnection myConn = new SqlConnection(connString);
static System.Data.SqlClient.SqlCommand cmdString = new System.Data.SqlClient.SqlCommand();
Those initializers will run the first time their containing class (Class1) is "touched" by the runtime. Because they aren't in a method, it's hard for the compiler to give a helpful stack trace when they fail. Try replacing the inline initializers with a static constructor:
static String connString;
static SqlConnection myConn;
static System.Data.SqlClient.SqlCommand cmdString;
static Class1() {
connString = ConfigurationManager.ConnectionStrings["Data Source=EVEDELL17;Initial Catalog=College;Integrated Security=True"].ConnectionString;
myConn = new SqlConnection(connString);
cmdString = new System.Data.SqlClient.SqlCommand();
}
I think you'll get a better error message that way. You can also set a breakpoint in the constructor to see exactly what happens during initialization.
Read more here: https://learn.microsoft.com/en-us/dotnet/api/system.typeinitializationexception?view=netframework-4.8#Static
Xander got the answer I think: Something goes "bump" when initializing those static fields. And static/type constructors are notoriously poor at communicating exceptions:
https://learn.microsoft.com/en-us/dotnet/api/system.typeinitializationexception
The underlying problem however, is one of pattern. And there are several issues. However you can often fudge these parts for simple learning examples.
Disposeable
SqlConnectons is Disposeable, as it contains some unmanaged resources. Always dispose of disposeables. My personal rule is:
never split the Creation and Disposing of a Disposeable resource. Create, Use, Dispose. All in the same piece of code - ideally using a using statement/block.
The rare exception is if you wrap around something disposeable that you can not Dispose (or even just might ocassionally). In that case implent the Dispose pattern yourself, with the sole purpose of relaying the Dispose() call. (Approxmialtey 95% of all classes are only Disposeable because of this).
Avoid Globals/Static
Static variables are global variables. And quicklly after inventing those, we realized that using either was a terrible idea 90% of the time. Particular for exchanging/sharing data.
While I go even a bit further, never have a field that is static and can be written. constant and readonly (runtime constants) should be the only statics you ever use. If you can not make it that, do not make it static. Stuff like connection strings are way up on that rule. If you can not tag it like that, do not make it a static to begin with.
At tops I make a class, struct or tupple. And assign a instance of it to a static readonly/constant variable. Stuff like connection strings are either a instance variable, or handed in on each call of a function like GetStudents. Indeed, Class1 looks a lot like a DB access abstraction. And those in particular fall under the "do not make static" rule.

Retrieving Data From a data source and displaying in a GridView

I am having problems getting data to be displayed in a gridview in VS 2010.
I have a SQLdataSource which is connecting to my database but the gridview is not showing at all, my error message is all that is displayed. Would anyone know why this is?
This is the code that I have:
`using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Data;
using System.Configuration;
using System.Web.Services.Description;
namespace DBprototype2
{
public partial class _Default : System.Web.UI.Page
{
void Page_Load(Object sender, EventArgs e)
{
// This example uses Microsoft SQL Server and connects
// to the Northwind sample database. The data source needs
// to be bound to the GridView control only when the
// page is first loaded. Thereafter, the values are
// stored in view state.
if(!IsPostBack)
{
// Declare the query string.
String queryString =
"SELECT * FROM ";
// Run the query and bind the resulting DataSet
// to the GridView control.
DataSet ds = GetData(queryString);
if (ds.Tables.Count > 0)
{
GridView1.DataSource = ds;
GridView1.DataBind();
Label1.Text = "Connected.";
}
else
{
Label1.Text = "Unable to connect to the database.";
}
}
}
DataSet GetData(String queryString)
{
// Retrieve the connection string stored in the Web.config file.
String connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
DataSet ds = new DataSet();
try
{
// Connect to the database and run the query.
SqlConnection connection = new SqlConnection(connectionString);
SqlDataAdapter adapter = new SqlDataAdapter(queryString, connection);
// Fill the DataSet.
adapter.Fill(ds);
Label1.Text = "Connected.";
}
catch(Exception ex)
{
// The connection failed. Display an error message.
Label1.Text = "Unable to connect.";
}
return ds;
}
}
}
`
If anyone could tell me the problem with my code that would be extremely helpful.
The problem is your query:
String queryString =
"SELECT * FROM ";
You are missing the table to select from, later in your method GetData you are not adding any table name in the query, that is why it is failing.
Also consider enclosing your connection in using statement
Use the Exception object ex.Message instead of hard coded error in label, this will help you debug and see what exactly is going wrong.
Not for this particular scenario but always consider using parametrized queries.

Calling class from code behind

I am still new to ASP.net and I'm learning how to call classes. I've looked around for tutorials, but not all are specific to ASP.net 4.0 so I'm not sure if I should apply them.
Right now, I am trying to connect to my SQL database. My webconfig file has been set up with the connectionstring "dbConnectionString" and is working properly when I've tested it with GridViews. What I'd like to do now is access the database from code behind.
I've seen some ways to accomplish this, but I'd like the most efficient, resuable way. I've tried to adopt the answer listed here: How to create sql connection with c# code behind, access the sql server then conditionally redirect? however, I'm getting an error.
I am doing this with C# as a website, not a web application. Here is my code behind for Login.aspx.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using SqlComm; // Is this how I connect to my class from this page????
public partial class Login : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
//no code written yet
}
}
}
My class in the App_Code folder, file name SQLComm.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.Web;
/// <summary>
/// SQL Query class
/// </summary>
public class SqlComm
{
// Connection string
static string DatabaseConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["dbConnectionString"].ConnectionString;
// Execute sql command with no value to return
public static void SqlExecute(string sql)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Connection.Open();
cmd.ExecuteNonQuery();
}
}
// Execute SQL query and return a value
public static object SqlReturn(string sql)
{
using (SqlConnection conn = new SqlConnection(PjSql.dbcs()))
{
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
object result = (object)cmd.ExecuteScalar();
return result;
}
}
// Retrieve an entire table or part of it
public static DataTable SqlDataTable(string sql)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Connection.Open();
DataTable TempTable = new DataTable();
TempTable.Load(cmd.ExecuteReader());
return TempTable;
}
}
// Execute a stored procedure with 1 parameter
// Returning a value or just executing with no returns
public static object SqlStoredProcedure1Param(string StoredProcedure, string PrmName1, object Param1)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
SqlCommand cmd = new SqlCommand(StoredProcedure, conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter(PrmName1, Param1.ToString()));
cmd.Connection.Open();
object obj = new object();
obj = cmd.ExecuteScalar();
return obj;
}
}
}
As you can see, I haven't written any code to actually use the class yet, but the "using SQLComm;" line itself is giving me this error:
Compiler Error Message: CS0246: The type or namespace name 'SqlComm' could not be found (are you missing a using directive or an assembly reference?)
As I'm still new, I'm unsure where to go from here. I seem to have included everything contained in the answer on the page I linked above. What else and I missing?
Edit: I read this post regarding a similar issue: asp.NET 2.0 Web Site Can't Access Classes in App_Code
Could this be because I am doing a website and not a web application, so the App_Code folder is being handled differently when I FTP the files over?
using SQLComm means you want to use the namespace SqlComm, which doesn't exist. I think what you want is (somewhere in your codebehind):
DataTable dt = SqlComm.SqlDataTable(...) // call one of the static methods.
You can call it directly.
Given your class has static methods only you'll call it like this:
SqlComm.SqlReturn("select * from table");
So I believe I figured it out. I had my App_Code folder within the subdirectory of my Aspx website, instead of in the root of the server. I moved the folder to the root and now it's working.
I'd be interested in hearing any answers to my edit to my original post though. Since I'm doing this as a website instead of a web application, are there any other issues I will need to keep in mind regarding using classes like this or other issues? I've looked around but haven't seen many differences.
Thanks to everyone for you help!

removing form from c# code?

I'm extremely new to C# and programming anything except for SQL. I've gotten the below code to happen on a Form and on a button click. If I wanted to just make this run on open, how would I do that? I'm very new to C# as you can tell (just started today learning it but its pretty exciting!)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Oracle.DataAccess.Client; // ODP.NET Oracle managed provider
using Oracle.DataAccess.Types;
namespace OraTrigger
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string oradb = "Data Source=OMP1;User Id=user;Password=pass;";
OracleConnection conn = new OracleConnection(oradb); // C#
conn.Open();
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT cast(Count(*) as varchar(20)) as trig FROM ZDMSN.TRIGGER_TEST";
//cmd.CommandType = CommandType.Text;
OracleDataReader dr = cmd.ExecuteReader();
dr.Read();
int cnt;
if (int.TryParse(dr.GetString(0), out cnt))
{
if (cnt > 0)
{
System.Diagnostics.Process.Start(#"C:\testfile.bat");
}
}
cmd.CommandText = "TRUNCATE TABLE ZDMSN.TRIGGER_TEST";
conn.Dispose();
}
}
}
If you need to run your code as a scheduled task then a command line application is more suitable.
Just create a new project and select Console Application.
Then move all of your button click code inside the Main method written for you by the Visual Studio IDE.
Rembember to set the references to the Oracle ODP.NET library and import the relevant using statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Oracle.DataAccess.Client; // ODP.NET Oracle managed provider
using Oracle.DataAccess.Types;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string oradb = "Data Source=OMP1;User Id=user;Password=pass;";
using(OracleConnection conn = new OracleConnection(oradb))
using(OracleCommand cmd = new OracleCommand("SELECT Count(*) as trig FROM ZDMSN.TRIGGER_TEST", conn))
{
conn.Open();
int cnt = (int)cmd.ExecuteScalar();
if (cnt > 0)
{
System.Diagnostics.Process.Start(#"C:\testfile.bat");
cmd.CommandText = "TRUNCATE TABLE ZDMSN.TRIGGER_TEST";
cmd.ExecuteNonQuery();
}
}
}
}
}
I have also revised your code to get a single value from the database. For this case is enough to use the Command.ExecuteScalar method that returns the first column of the first row obtained from your sql command text. Because the count(*) should Always return a single row you could easily cast the return value of ExecuteScalar to your record count variable.
EDIT I have added the logic to TRUNCATE the table involved. Please pay attention that you should use the code provided here. Your code will probably fail because you have an open DataReader and when a DataReader is open you cannot execute other commands (This is true for SqlServer without Multiple Active Result Sets enabled, I really don't know if this rules applies also to the Oracle NET Provider)
Subscribe to Shown or Load event of form and move your code to that event handler.
Form.Shown Event Occurs whenever the form is first displayed.
Form.Load Event Occurs before a form is displayed for the first time.
Also I suggest to extract your code to some Data Access related class, or at least to separate method. And call that method from event handler.

Where/how do I write T-SQL in my C# code and get the result (Visual Studio 2008)

I am trying to write t-sql in C# (visual studio). I have this code to connect to the database:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
using Microsoft.SqlServer.Server;
namespace WindowsFormsApplication8
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string connetionString = null;
SqlConnection cnn;
connetionString = "Data Source=.\\SQLEXPRESS;AttachDbFilename=C:\\Users\\Xtreme\\Desktop\\CardsDB.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True";
cnn = new SqlConnection(connetionString);
try
{
cnn.Open();
MessageBox.Show("Connection Open ! ");
cnn.Close();
}
catch (Exception ex)
{
MessageBox.Show("Can not open connection ! ");
}
}
}
}
Where/how do I write the T-SQL code and how do I get the result?
Can someone give me an simple select example in my code?
You can use DataAdapter.Fill Method:
try
{
using (SqlDataAdapter a = new SqlDataAdapter("SELECT * FROM Employee", cnn))
{
// Use DataAdapter to fill DataTable
DataTable t = new DataTable();
a.Fill(t);
// Render data onto the screen
dataGridView1.DataSource = t; //if you want.
}
}
catch (Exception ex)
{
MessageBox.Show("Problem!");
}
Create a SqlCommand and set the CommandType to CommandType.Text. Then add your SQL to the CommandText property of the SqlCommand.
SqlCommand command = new SqlCommand(commandName, (SqlConnection)Connection);
command.CommandType = CommandType.Text;
command.CommandText = "SELECT * FROM MyTable";
IDataReader result = command.ExecuteReader();
Ardman already showed you how to execute any arbitary sql command. But what i didn't answer very well, is where to put your sql statement.
I think it is a very bad behaviour and also not very good to read if you put your statement directly into the code.
A better method (in my eyes) is the following:
Within your project create a new folder (maybe called Queries)
Right click this folder and select Add - New Item
In the dialog just select Textfile and give it the name about what this query will do
Make sure you replace the file extension from .txt to .sql
Just put your statement right into this file
In the Resource Editor add this file as a resource
Now you can access this sql statement within your project just by using Properties.Resources.MySqlStatement

Categories

Resources