SqlException was unhandled, C# [closed] - c#

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
What should I do with this error? I used this code in selectall method and everything was fine, but in selectrow I get this error.
Code:
public DataTable SelectRow(string ContactID)
{
string query = "Select * from ContactsList Where ContactID = #ID";
SqlConnection connection = new SqlConnection(ConnectionString);
SqlDataAdapter adapter = new SqlDataAdapter(query, connection);
DataTable data = new DataTable();
adapter.Fill(data);
return data;
}
Error:
An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
Additional information:
Must declare the scalar variable "#ID".

The following code
Creates a parameter as a parameter should be done and as recommended by #Olivier Rogier.
Does not use a DataAdapter, seeing you have it as a local var indicates this. Use a command object instead.
Note the return type carries the DataTable if no errors while if a runtime exception is raised the Exception is passed back to the caller.
Recommend not using SELECT * (not part of the question but better to ask for that which is needed and no more).
Code
public class DataOperations
{
private static string connection = "Data Source=.\\sqlexpress;Initial Catalog=NorthWind2020;Integrated Security=True";
public static (DataTable table, Exception exception) SelectRow(string contactId)
{
DataTable table = new DataTable();
try
{
using (var cn = new SqlConnection { ConnectionString = connection })
{
using (var cmd = new SqlCommand { Connection = cn })
{
cmd.CommandText = "SELECT FirstName, LastName FROM dbo.Contacts WHERE ContactId = #contactId;";
cmd.Parameters.Add("#contactId", SqlDbType.NVarChar).Value = contactId;
cn.Open();
table.Load(cmd.ExecuteReader());
return (table, null);
}
}
}
catch (Exception exception)
{
return (null, exception);
}
}
}
Sample code to call method above.
var (dataTable, exception) = DataOperations.SelectRow(contactIdentifier);
if (exception == null)
{
Debug.WriteLine("Use table");
}
else
{
Debug.WriteLine(exception.Message);
}
Also, if the contact identifier is pointing to a single record you could simply pass a single DataRow back rather than an entire DataTable or use a single instance of a class e.g.
public class Contact
{
// seems this would be an int
public string ContactId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public override string ToString() => $"{FirstName} {LastName}";
}
Code to get data
public static Contact SelectContact(string contactId)
{
Contact contact = new Contact() {ContactId = contactId};
using (var cn = new SqlConnection { ConnectionString = connection })
{
using (var cmd = new SqlCommand { Connection = cn })
{
cmd.CommandText = "SELECT FirstName, LastName FROM dbo.Contacts WHERE ContactId = #contactId;";
cmd.Parameters.Add("#contactId", SqlDbType.NVarChar).Value = contactId;
cn.Open();
var reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
contact.FirstName = reader.GetString(0);
contact.LastName = reader.GetString(1);
}
}
}
return contact;
}

Passing Scalar Variable to SQL Raw Query (Must declare the scalar variable)
You have declared the parameter #ID but didn't pass the value for the parameter.
I have modified your code as below.
public DataTable SelectRow(string ContactID)
{
SqlConnection connection = new SqlConnection(ConnectionString);
string query = "Select * from ContactsList Where ContactID = #ID";
SqlCommand cmd=new SqlCommand(query,connection);
cmd.CommandType=CommandType.Text;
cmd.Parameters.AddWithValue("#ID",ContactID);
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataTable data = new DataTable();
adapter.Fill(data);
return data;
}
You can pass the SqlCommand object "cmd" to the SqlDataAdapter constructor which will load the data as per the specified query to the "adapter" object.
Hoping that the above code will be helpful to you.

Related

C# Method Overloading - 2 methods with similar parameters

I have two methods that have similar input parameter types, but the parameters themselves are different and used to build an SQL statement within the method.
C# doesn't like this - "Type Database already defines a member called 'DatabaseSearch' with the same parameter types."
As a newbie, this sounds to me like I'm structuring the class or methods wrong?
Should I perhaps be building the SQL statement outside the method and passing it and its parameters in?
// Surname ONLY
public void DatabaseSearch(DataGrid DataGrid, string surname)
{
string database_file_path = #"Data Source=.\MemberDB.db";
string sqlCmd = "Select * FROM Members WHERE Surname = #surname";
using (var con = new SQLiteConnection(database_file_path))
{
using (var cmd = new SQLiteCommand(con))
{
con.Open();
cmd.Parameters.AddWithValue("#surname", surname);
cmd.CommandText = sqlCmd;
var dataAdapter = new SQLiteDataAdapter(cmd);
var dt = new DataTable("Members");
dataAdapter.Fill(dt);
DataGrid.ItemsSource = dt.DefaultView;
dataAdapter.Update(dt);
}
}
}
// Firstname ONLY
public void DatabaseSearch(DataGrid DataGrid, string firstname)
{
string database_file_path = #"Data Source=.\MemberDB.db";
string sqlCmd = "Select * FROM Members WHERE FirstName = #firstname";
using (var con = new SQLiteConnection(database_file_path))
{
using (var cmd = new SQLiteCommand(con))
{
con.Open();
cmd.Parameters.AddWithValue("#firstname", firstname);
cmd.CommandText = sqlCmd;
var dataAdapter = new SQLiteDataAdapter(cmd);
var dt = new DataTable("Members");
dataAdapter.Fill(dt);
DataGrid.ItemsSource = dt.DefaultView;
dataAdapter.Update(dt);
}
}
}
Summary:
How do you have two overloaded methods with the same types of parameters?
public void myMethod( int one, string one){
....some stuff done...
}
public void myMethod( int two, string two){
....different stuff done...
}
You can either change the method name or change the order of the parameters. The first approach is better.
public void DatabaseSearchByFirstName(int one, string one){
// ...some stuff done...
}
public void DatabaseSearchBySurName(int two, string two){
// ...different stuff done...
}

Initializing Combo Box in C# Access

I was trying to add a combo box which could get all the product name but unfortunately I follow some tutorials and end up like this.
void fillCombo()
{
try
{
con.Open();
OleDbCommand command = new OleDbCommand("Select * from IblInventory");
command.Connection = con;
OleDbDataReader reader = command.ExecuteReader();
while (reader.Read())
{
String product = reader.GetString("ProductName"); // << invalid argument
cmbProduct.Items.Add(product);
}
con.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
What could possibly the reason?
From the documentation of OleDbDataReader.GetString you will notice that the argument required by the method is an integer representing the position of the column in the returned record not its name.
If you (rightly) prefer to use the column name then you need to take a detour and use the GetOrdinal method to retrieve the position of the column given the name.
while (reader.Read())
{
int pos = reader.GetOrdinal("ProductName");
String product = reader.GetString(pos);
cmbProduct.Items.Add(product);
}
Another example, practically identical to your situation, can be found in the documentation page on MSDN about OleDbDataReader.GetOrdinal
It is also a common practice to write an extension method that allows you to write code as yours hiding the details of the mapping between name and position. You just need a static class with
public static class ReaderExtensions
{
public string GetString(this OleDbDataReader reader, string colName)
{
string result = "";
if(!string.IsNullOrEmpty(colName))
{
int pos = reader.GetOrdinal(colName);
result = reader.GetString(pos);
}
return result;
}
... other extensions for Int, Decimals, DateTime etc...
}
Now with this class in place and accessible you can call
string product = reader.GetString("ProductName");
it is working in my project
First fill your data in to datatable see the below code
DataTable results = new DataTable();
using(OleDbConnection conn = new OleDbConnection(connString))
{
OleDbCommand cmd = new OleDbCommand("Select * from IblInventory", conn);
conn.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter(cmd);
adapter.Fill(results);
}
Now
cmbProduct.DataSource = results ;
cmbProduct.DisplayMember = "ProductName";
cmbProduct.ValueMember = "Id feild of IblInventory table";

DataTable Always Returns 0

My query returns results, but for some reason my DataTable always shows 0. The only thing I altered was the fact that I added parameters to the C# syntax (altho if I manually run the stored procedure it returns results). This is my syntax, does anyone see something that is incorrect syntactically in it?
protected void btnPress1464()
{
RunSQLStoredProc();
DataTable tableA = ebdb.Tables[0];
if (this.dtgAttendanceTracker.Items.Count == 0)
{
this.gvwTest.DataSource = tableA
this.gvwTest.DataBind();
}
}
public DataSet RunSQLStoredProc()
{
ebdb = new DataSet();
SqlQueryBuilder = new StringBuilder();
SqlQueryBuilder.Append("exec alphadawg ");
ebdb = DoThis(SqlQueryBuilder.ToString());
return ebdb;
}
public DataSet DoThis(string sqlQuery, int employeeid, DateTime hiredate, DateTime terminationdate)
{
try
{
System.Configuration.ConnectionStringSettings connstring = System.Configuration.ConfigurationManager.ConnectionStrings["SQLServer1"];
using (SqlConnection conn = new SqlConnection(connstring.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = sqlQuery;
cmd.Connection = conn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#employeeid", employeeid.ToString());
cmd.Parameters.AddWithValue("#hiredate", hiredate.ToShortDateString());
cmd.Parameters.AddWithValue("#terminationdate", terminationdate.ToShortDateString());
conn.Open();
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
adapter.Fill(ebdb);
conn.Close();
}
}
return ebdb;
}
catch (Exception exception) { throw exception; }
}
The CommandText should only contain the stored-procedure name and not also exec if the command's CommandType is StoredProcedure. The StringBuilder is also redundant.
I also think that the way how you use AddWithValue with the wrong types could cause this issue(look at the last paragraph of my answer):
So not
SqlQueryBuilder = new StringBuilder();
SqlQueryBuilder.Append("exec alphadawg ");
ebdb = DoThis(SqlQueryBuilder.ToString());
but
ebdb = DoThis("alphadawg", otherParamaters...);
It's also bad practice to pass a sql-string to a method that executes it, that often introduces sql injection issues. You should not have a method DoThis but GetAlphaDawg which encapsulates the sql-query and only pass the parameter-values.
Apart from that, why do you return the DataSet from a method if it's actually a field in your class that you return? Instead initialize and fill it in the method, that's much clearer and also prevents issues when you load an already filled dataset(data will be appended by default).
This would be a possible implementation. Note that you shouldn't use AddWithValue and don't use String for DateTime but always use the correct type, all the more if you use AddWithValue which needs to infer the type from the value:
public DataSet GetAlphaDawg(int employeeid, DateTime hiredate, DateTime terminationdate)
{
DataSet dsAlpha = new DataSet();
try
{
System.Configuration.ConnectionStringSettings connstring = System.Configuration.ConfigurationManager.ConnectionStrings["SQLServer1"];
using (var conn = new SqlConnection(connstring.ConnectionString))
{
using (var da = new SqlDataAdapter("alphadawg", conn))
{
da.SelectCommand.CommandType = CommandType.StoredProcedure;
var parameter = da.SelectCommand.Parameters;
parameter.Add("#employeeid", SqlDbType.Int).Value = employeeid;
parameter.Add("#hiredate", SqlDbType.Date).Value = hiredate;
parameter.Add("#terminationdate", SqlDbType.Date).Value = terminationdate;
da.Fill(dsAlpha); // Open/Close not needed with Fill
return dsAlpha;
}
}
} catch (Exception) { throw; }
}
Since you use ToShortDateString, if you actually want to remove the time portion of your DateTime use DateTime.Date, for example:
parameter.Add("#hiredate", SqlDbType.Date).Value = hiredate.Date;

Converting datatable to int directly in c#

I tried to convert a datatable that just has one field (the field's data is primary key) to int , in order to using in sql commands such as Select and etc.
but it fails!
and when i cast it to an object or convert it to string first , the commands gone wrong!
please help me
i want to select * from a table which has a foreign key where the foreign code equals by an int value that has been selected from a table in another sql command and returned as a datatable row with just one field.
here is my code :
class mydata :
public string strsql;
public DataTable showData()
{
SqlConnection Con1 = new SqlConnection("Data Source=.;database=daneshgah;integrated security=true");
Con1.Open();
SqlDataAdapter da = new SqlDataAdapter(strsql, Con1);
DataTable dt = new DataTable();
da.Fill(dt);
Con1.Close();
return (dt);
}
button event :
myData search = new myData();
int aa = int.Parse(txt_stdcourse.Text);
search.strsql = "select tchNo from University where couNo='" + aa + "'";
DataTable a = search.showData();
string b = a.Rows[0][0].ToString();
int c = int.Parse(b);
myData akhz = new myData();
akhz.strsql = "insert into stc (couNo,tchNo,stuNo)values('" + aa + "','" + c + "','" + id + "')";
akhz.Data();
lbl_stdcourseok.Visible = false;
lbl_stdcourseok.Visible = true;
Sounds like you need to use ExecuteScalar on a SqlCommand instead of using a DataAdapter. ExecuteScalar gives the first column of the first row of the dataset returned.
public object RunSQL(string sql)
{
SqlConnection Con1 = new SqlConnection("Data Source=.;database=daneshgah;integrated security=true");
Con1.Open();
SqlCommand command = new SqlCommand(strsql, Con1);
return command.ExecuteScalar();
}
//In some event handler
int myValue = (int)RunSQL("Select Value from Table where ID = " + ID);
That said, please don't do that - it is very bad practice. You almost certainly want to create a class that models whatever data objects you are dealing with, instead of executing arbitrary SQL from event handlers. It is also probably best to manage connections independently of your data class, in a separate data access layer.
An extremely rudimentary example:
public class Student
{
public int StudentID { get; set; }
public bool CurrentlyEnrolled { get; set; }
public string Name { get; set; }
public static Student LoadByID(int ID)
{
DataTable results = DAL.ExecuteSQL("Select * from Students WHERE StudentID = #StudentID", new SqlParameter("#StudentID", ID));
if (results.Rows.Count == 1)
{
return FillFromRow(results.Rows[0]);
}
else
{
throw new DataException("Could not find exactly one record with the specified ID.");
}
}
private static Student FillFromRow(DataRow row)
{
Student bob = new Student();
bob.CurrentlyEnrolled = (bool)row["CurrentlyEnrolled"];
bob.Name = (string)row["Name"];
bob.StudentID = (int)row["StudentID"];
return bob;
}
}
public static class DAL
{
private const string ConnectionString = "SomeConnectionString"; //Should really be stored in configuration files.
public static DataTable ExecuteSQL(string SQL, params SqlParameter[] parameters)
{
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
using (SqlCommand command = new SqlCommand(SQL))
{
command.Parameters.AddRange(parameters);
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
DataTable result = new DataTable();
adapter.Fill(result);
return result;
}
}
}
}
}

Retrieve distinct row and declaring scalar variable

I am trying to retrieve a distinct row from my Database from a particular "deliverySerial".
However I encountered an error which prompt me to "Declare Scalar Variable ="#deliverySerial".
I had tried many other ways but still problems still persist.
Here is the connection:
public class DlDbConn
{
public DlDbConn()
{
}
public SqlConnection GetConnection()
{
SqlConnection dbConn;
dbConn = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\test.mdf;Integrated Security=True;User Instance=True");
return dbConn;
}
}
Method in the data layer:
private String errMsg;
private DlDbConn dbConn;
public testing()
{
dbConn = new DlDbConn();
}
public DataSet Details(String supplierLogo, String supplierName, String supplierAddr, int poNum, String dateSent, int deliverySerial, String deliveryDate,
int quantity, String catSerial, String catName)
{
SqlConnection conn;
StringBuilder sql;
SqlDataAdapter da;
DataSet detail;
conn = dbConn.GetConnection();
detail = new DataSet();
sql = new StringBuilder();
sql.AppendLine("SELECT * FROM (select PO.poNum, PO.dateSent, ViewDelivery.deliverySerial, Supplier.supplierName, Supplier.supplierAddr, Supplier.supplierLogo, ViewDelivery.deliveryDate, Catalog.catSerial, Catalog.catName, PO.quantity, ROW_NUMBER() OVER (PARTITION BY Catalog.catSerial ORDER BY Catalog.catSerial) AS num FROM PO INNER JOIN Supplier ON PO.supplierID = Supplier.supplierID INNER JOIN ViewDelivery ON PO.poNum = ViewDelivery.poNum INNER JOIN Catalog ON PO.catSerial = Catalog.catSerial)AS a WHERE a.num = 1 ");
sql.AppendLine("AND ViewDelivery.deliverySerial = #deliverySerial");
try
{
conn.Open();
da = new SqlDataAdapter(sql.ToString(), conn);
da.SelectCommand.Parameters.AddWithValue("#deliverySerial", deliverySerial);
da.Fill(detail);
}
catch (Exception ex)
{
errMsg = ex.Message;
}
finally
{
conn.Close();
}
return detail;
}
You must use parameter notation for MySQL i.e. ? instead of #deliverySerial in your query.
Also, table ViewDelivery not accessible in outer part of query.
Use:
AND a.deliverySerial = ?
I think your query is incorrect. Here is the Fiddle -- you can't query on ViewDelivery since it's outside of your subquery.
Try removing that from your WHERE criteria since that field is returned in your subquery:
sql.AppendLine("AND deliverySerial = #deliverySerial");
I don't think you need the "?", but I could be mistaken.
Good luck.

Categories

Resources