Listbox Selected Value Issue - c#

I have a list box on my WinForms application which populates with the following SQL code in C#:
private void PopulateClients()
{
string sqlText = "SELECT ClientID, ClientName FROM tblClients;";
cSqlQuery cS = new cSqlQuery(sqlText, "table");
lbxClient.DataSource = cS.cTableResults;
lbxClient.DisplayMember = "ClientName";
lbxClient.ValueMember = "ClientID";
}
So whilst the list box displays client names, the value it should return when selected is the numerical clientID.
However, later in the code -
private void btnAddNewJob_Click(object sender, EventArgs e)
{
try
{
string strNewJobName = txtNewJobName.Text;
string strNewJobRef = txtNewJobRef.Text;
int intNewJobClient = (int)lbxClient.SelectedValue;
string sqlText = "INSERT INTO tblJobs (JobID, JobClient, JobRef, JobName) " +
"VALUES (#JobID, #JobClient, #JobRef, #JobName);";
SqlCommand sqlCom = new SqlCommand(sqlText);
sqlCom.Parameters.Add("#JobID", SqlDbType.Int);
sqlCom.Parameters.Add("#JobClient", SqlDbType.Int);
sqlCom.Parameters.Add("#JobRef", SqlDbType.Text);
sqlCom.Parameters.Add("#JobName", SqlDbType.Text);
cConnectionString cS = new cConnectionString();
sqlCom.Parameters["#JobID"].Value = cS.NextID("JobID", "tblJobs");
sqlCom.Parameters["#JobClient"].Value = intNewJobClient;
sqlCom.Parameters["#JobRef"].Value = strNewJobRef;
sqlCom.Parameters["#JobName"].Value = strNewJobName;
cSqlQuery cQ = new cSqlQuery(sqlCom, "non query");
PopulateJobs();
txtNewJobName.Text = "";
txtNewJobRef.Text = "";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Fails on the third line
int intNewJobClient = (int)lbxClient.SelectedValue;
With an invalid cast. As far as I can see the listbox is still returning the Client Name, whereas it should be returning then numerical clientID (int).
Any ideas?

Your code should work - just tested that.
Make sure that the data you are binding to is correct - especially ClientID
also make sure that the value is selected before casting to int
Hope it helps

lbxClient.SelectedValue is a string. It should be converted to an int like so:
int intNewJobClient = Convert.ToInt32(lbxClient.SelectedValue);
Hope this helps.

In the end I had to do this:
int intClient = 0;
try
{
intClient = (int)lbxClient.SelectedValue;
}
catch (Exception)
{
intClient = 0;
}
Which I feel like is a bit of a fudge - but it works!

You code should work, However you should place a sanity check on the SelectedValue on the index.
if (lbxClient.SelectedIndex != -1)
{
int intClient = 0;
try
{
intClient = Convert.ToInt32(lbxClient.SelectedValue);
}
catch (Exception)
{
// catch if the value isn't integer.
intClient = -1;
}
}

I had the same problem but its resolved now by doing this
Replace this
lbxClient.DataSource = cS.cTableResults;
lbxClient.DisplayMember = "ClientName";
lbxClient.ValueMember = "ClientID";
With
lbxClient.DisplayMember = "ClientName";
lbxClient.ValueMember = "ClientID";
lbxClient.DataSource = cS.cTableResults;
Just place the first line "DataSource=" in last and the you will get rid out of it :)
The reason is doing this explained in #Sebastian answer.

Related

Parameter '?user_email' not found in the collection

I am using MySql 5.6x with Visual Studio 2015, windows 10, 64-bit. C# as programming language. In my CRUD.cs (Class file) i have created the following method:
public bool dbQuery(string sql,string[] paramList= null)
{
bool flag = false;
try
{
connect();
cmd = new MySqlCommand(sql,con);
cmd.Prepare();
if(paramList != null){
foreach(string i in paramList){
string[] valus = i.Split(',');
string p = valus[0];
string v = valus[1];
cmd.Parameters[p].Value = v;
}
}
if (cmd.ExecuteNonQuery() > 0)
{
flag = true;
}
}
catch (Exception exc)
{
error(exc);
}
}
I am passing the query and Parameters List like this:
protected void loginBtn_Click(object sender, EventArgs e)
{
string sql = "SELECT * FROM dept_login WHERE (user_email = ?user_email OR user_cell = ?user_cell) AND userkey = ?userkey";
string[] param = new string[] {
"?user_email,"+ userid.Text.ToString(),
"?user_cell,"+ userid.Text.ToString(),
"?userkey,"+ userkey.Text.ToString()
};
if (db.dbQuery(sql, param))
{
msg.Text = "Ok";
}
else
{
msg.Text = "<strong class='text-danger'>Authentication Failed</strong>";
}
}
Now the problem is that after the loop iteration complete, it directly jumps to the catch() Block and generate an Exception that:
Parameter '?user_email' not found in the collection.
Am i doing this correct to send params like that? is there any other way to do the same?
Thanks
EDIT: I think the best way might be the two-dimensional array to collect the parameters and their values and loop then within the method to fetch the parameters in cmd.AddWidthValues()? I may be wrong...
In your dbQuery you don't create the parameters collection with the expected names, so you get the error when you try to set a value for a parameter that doesn't exist
public bool dbQuery(string sql,string[] paramList= null)
{
bool flag = false;
try
{
connect();
cmd = new MySqlCommand(sql,con);
cmd.Prepare();
if(paramList != null){
foreach(string i in paramList){
string[] valus = i.Split(',');
string p = valus[0];
string v = valus[1];
cmd.Parameters.AddWithValue(p, v);
}
}
if (cmd.ExecuteNonQuery() > 0)
flag = true;
}
catch (Exception exc)
{
error(exc);
}
}
Of course this will add every parameter with a datatype equals to a string and thus is very prone to errors if your datatable columns are not of string type
A better approach would be this one
List<MySqlParameter> parameters = new List<MySqlParameter>()
{
{new MySqlParameter()
{
ParameterName = "?user_mail",
MySqlDbType= MySqlDbType.VarChar,
Value = userid.Text
},
{new MySqlParameter()
{
ParameterName = "?user_cell",
MySqlDbType= MySqlDbType.VarChar,
Value = userid.Text
},
{new MySqlParameter()
{
ParameterName = "?userkey",
MySqlDbType = MySqlDbType.VarChar,
Value = userkey.Text
},
}
if (db.dbQuery(sql, parameters))
....
and in dbQuery receive the list adding it to the parameters collection
public bool dbQuery(string sql, List<MySqlParameter> paramList= null)
{
bool flag = false;
try
{
connect();
cmd = new MySqlCommand(sql,con);
cmd.Prepare();
if(paramList != null)
cmd.Parameters.AddRange(paramList.ToArray());
if (cmd.ExecuteNonQuery() > 0)
{
flag = true;
}
}
catch (Exception exc)
{
error(exc);
}
}
By the way, unrelated to your actual problem, but your code doesn't seem to close and dispose the connection. This will lead to very nasty problems to diagnose and fix. Try to use the using statement and avoid a global connection variable
EDIT
As you have noticed the ExecuteNonQuery doesn't work with a SELECT statement, you need to use ExecuteReader and check if you get some return value
using(MySqlDataReader reader = cmd.ExecuteReader())
{
flag = reader.HasRows;
}
This, of course, means that you will get troubles when you want to insert, update or delete record where instead you need the ExecuteNonQuery. Creating a general purpose function to handle different kind of query is very difficult and doesn't worth the work and debug required. Better use some kind of well know ORM software like EntityFramework or Dapper.
Your SQL Commands' Parameters collection does not contain those parameters, so you cannot index them in this manner:
cmd.Parameters[p].Value = v;
You need to add them to the Commands' Parameters collection in this manner: cmd.Parameters.AddWithValue(p, v);.

why does this string always revert to ""?

Heres my code:
public userScreen(string uName)
{
InitializeComponent();
userName = uName;
string topLogNumber = "0";
textBox2.Text = userName;
Conversion(topLogNumber);
textBox1.Text = topLogNumber;
this.WindowState = FormWindowState.Maximized;
private string Conversion(string lognumber)
{
lognumber = gettoplognumber();
int lognumberint = Convert.ToInt32(lognumber);
lognumberint = lognumberint+1;
lognumber = lognumberint.ToString();
return lognumber;
}
private string gettoplognumber()
{
string selectTopLogNumber = "SELECT MAX (LogNo) from Logs";
string connection = "Data Source = \"EventControl.sdf\"";
SqlCeConnection connexion = new SqlCeConnection(connection);
SqlCeCommand topLog = new SqlCeCommand(selectTopLogNumber, connexion);
try
{
connexion.Open();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
return "error";
}
return topLog.ExecuteScalar() as string;
Now, what this code does is look into a database and increments the number by one. When it runs through (I have debugged the whole process), for some reason its all fine, until it reaches textBox1.Text = topLogNumber; at which point it changes back to "". Anyone????
Change this line to get the result of Conversion
topLogNumber = Conversion(topLogNumber);
or just assign the result of Conversion to your textbox
textBox1.Text = Conversion(topLogNumber);
The result of the calculation inside Conversion is passed back in the return statement. You need to reassign the result of that calc to the variable topLogNumber used inside the userScreen.

AS400 RPG Program not returning anything

I have the following code. The program just exits, no value returned from call. Any ideas?
AS400System system = new AS400System();
system.Define(ConfigurationManager.AppSettings["AS400Server"]);
system.UserID = ConfigurationManager.AppSettings["AS400User"];
system.Password = ConfigurationManager.AppSettings["AS400Password"];
system.IPAddress = "10.98.1.21";
system.Connect(cwbcoServiceEnum.cwbcoServiceRemoteCmd);
if(system.IsConnected(cwbcoServiceEnum.cwbcoServiceRemoteCmd) == 1) {
Program program = new Program();
program.LibraryName = "P2PTST";
program.ProgramName = "AUI0XFR";
program.system = system;
program.system.Signon();
string paramStatus = "A";
Int64 paramStockItem = Int64.Parse(t.EtagNumber);
Guid paramGuid = Guid.NewGuid();
string paramReturn;
StringConverter stringConverter = new StringConverter();
ProgramParameters parameters = new ProgramParameters();
parameters.Append("ApiIGuid", cwbrcParameterTypeEnum.cwbrcInout, 38);
parameters.Append("StockItemNumber", cwbrcParameterTypeEnum.cwbrcInout, 20);
parameters.Append("ItemStatus", cwbrcParameterTypeEnum.cwbrcInout, 1);
parameters.Append("ReturnCode", cwbrcParameterTypeEnum.cwbrcInout, 7);
parameters["ApiIGuid"].Value = stringConverter.ToBytes(paramGuid.ToString().PadRight(38, ' '));
parameters["StockItemNumber"].Value = stringConverter.ToBytes(paramStockItem.ToString().PadRight(20, ' '));
parameters["ItemStatus"].Value = stringConverter.ToBytes(paramStatus.ToString());
try{
program.Call(parameters);
paramReturn = stringConverter.FromBytes(parameters["ReturnCode"].Value);
system.Disconnect(cwbcoServiceEnum.cwbcoServiceAll);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
We just went through this and had the same issues, so decided to create and use a stored procedure to accomplish this in .NET. Because we were concerned about having the 400 side distribute the code to create a stored procedure, it ended up being very quick to go ahead and create the procedure on the PC side, followed by our remote command, so no additional changes were necessary on the 400 side.
My environment is Win7 x64 running VS2012 C#, CAX V7.1, and importing both IBM.Data.DB2.iSeries, and System.Data;
I need System.Data for the Parameters. That ended up being critical to get data back!
I send the 400 two params, filesetID and a name. I get back a number and a uuid.
(but they are all characters!)
It looks something like this:
public void RemoteCmd(ref PicMeta pm)
{
iDB2Connection cn;
try
{
using (cn = new iDB2Connection("DataSource=<servername/IP>; UserID="<user>"; Password="<pass>";"))
{
cn.Open();
using (iDB2Command cm = cn.CreateCommand())
{
//Place a try/catch here, so it will create the procedure the first time, or any time it has been removed from the 400. If already set, it will fail, and you'll go directly to the remote command.
try
{
//Here we create a procedure and execute or continue.
cm.CommandText = "CREATE PROCEDURE LIBRARY.SP_PICGETID(INOUT FSET CHAR (1 ), INOUT UNIT CHAR (6 ), INOUT NEXTID CHAR (3 ), INOUT UUID CHAR (36 )) LANGUAGE RPGLE NOT DETERMINISTIC NO SQL CALLED ON NULL INPUT EXTERNAL NAME LIBRARY.PICGETID PARAMETER STYLE GENERAL";
cm.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.Out.WriteLine(ex.Message);
}
//Continue - create and call the command
//ParameterDirection needs "using System.Data;"
cm.CommandTimeout = 0;
cm.CommandType = System.Data.CommandType.StoredProcedure;
cm.CommandText = "LIBRARY.SP_PICGETID";
iDB2Parameter p = new iDB2Parameter();
p.ParameterName = "FSET";
p.Direction = ParameterDirection.Input;
p.iDB2DbType = iDB2DbType.iDB2Char;
p.Size = 1;
p.iDB2Value = pm.fileset;
cm.Parameters.Add(p);
p = new iDB2Parameter();
p.ParameterName = "UNIT";
p.Direction = ParameterDirection.Input;
p.iDB2DbType = iDB2DbType.iDB2Char;
p.Size = 6;
p.iDB2Value = pm.unit;
cm.Parameters.Add(p);
p = new iDB2Parameter();
p.ParameterName = "NEXTID";
p.Direction = ParameterDirection.InputOutput;
p.iDB2DbType = iDB2DbType.iDB2Char;
p.Size = 3;
p.iDB2Value = "";
cm.Parameters.Add(p);
p = new iDB2Parameter();
p.ParameterName = "GUUID";
p.Direction = ParameterDirection.InputOutput;
p.iDB2DbType = iDB2DbType.iDB2Char;
p.Size = 36;
p.iDB2Value = "";
cm.Parameters.Add(p);
cm.ExecuteNonQuery();
iDB2ParameterCollection pc = cm.Parameters;
//We get our Out parameters here
pm.nextid = pc["NEXTID"].Value.ToString();
pm.uuid = pc["GUUID"].Value.ToString();
}
cn.Close();
}
}
catch (Exception e)
{
Console.Out.WriteLine(e.Message);
}
return;
}
Hope this helps!

C# adding data to SQL database

Background:
I am trying to add data to a SQL DB with C#. I am currently doing so in my script in another class so im using the same code (the code works). However, my current class is using a bunch of recycled code and i am having issues narrowing down why i can not write to the DB. Below is the code i am using and it is broken down to the bare bones minimum code.
What I'm asking for:
anyone to point out some dumb mistake i made or ideas where to troubleshoot. Currently i am just staring at this code and cant see whats wrong.
Thanks in advance!
public void AddAttachmentToDB(XmlNode root, XmlNamespaceManager xmlns, string MessageID, string MailBoxAliasName)
{
//open DB
#region Open DB
if (DbConnection.State != System.Data.ConnectionState.Open)
{
try
{
this.DbConnection.ConnectionString = DbConnectionString;
this.DbConnection.Open();
MailboxListener._logging.LogWrite("[{0}] opened DB Connection in AddAttachmentToDB!",
LoggingLevels.Error,
System.Reflection.MethodBase.GetCurrentMethod().ToString(),
this.DbConnectionString);
}
catch (Exception ex)
{
MailboxListener._logging.LogWrite("[{0}] Failed to open DB Connection! For Machine: {1}",
LoggingLevels.Error,
System.Reflection.MethodBase.GetCurrentMethod().ToString(),
this.DbConnectionString);
MailboxListener._logging.LogWrite("[{0}] Error Returned: {1}",
LoggingLevels.Error,
System.Reflection.MethodBase.GetCurrentMethod().ToString(),
ex.Message.ToString());
}
}
else
{
MailboxListener._logging.LogWrite("[{0}] Failed to open DB Connection in AddAttachmentToDB!",
LoggingLevels.Error,
System.Reflection.MethodBase.GetCurrentMethod().ToString(),
this.DbConnectionString);
}
#endregion
//once db is open try this
try
{
//create test variables
string strMailBoxAliasName = MailBoxAliasName;
string AttachmentFilename = string.Empty;
string strfiletype = string.Empty;
string AttachmentStream = string.Empty;
string strAttachmentID = string.Empty;
string strMessageID = string.Empty;
strMessageID = MessageID;
//fill test variables
AttachmentFilename = "yumyum";
AttachmentStream = "Cheetos";
strMessageID = "123";
strMailBoxAliasName = "user";
strfiletype = ".txt";
strAttachmentID = "12345";
//create sql insert string
String insString = #"INSERT INTO MailboxListenerAttachments Values (#attachmentfilename, #attachmentbody,
#messageID, #mailboxname, #filetype, #attachmentID, #DateAddedToDB)";
//create sql command string
SqlCommand myCommand = new SqlCommand(insString, this.DbConnection);
//add fill test variables to sql insert string
myCommand.Parameters.Add("#attachmentfilename", SqlDbType.VarChar, 100);
myCommand.Parameters["#attachmentfilename"].Value = AttachmentFilename;
myCommand.Parameters.Add("#attachmentbody", SqlDbType.VarChar, 8000);
myCommand.Parameters["#attachmentbody"].Value = AttachmentStream.Trim();
myCommand.Parameters.Add("#messageID", SqlDbType.VarChar, 500);
myCommand.Parameters["#messageID"].Value = strMessageID;
myCommand.Parameters.Add("#mailboxname", SqlDbType.VarChar, 100);
myCommand.Parameters["#mailboxname"].Value = strMailBoxAliasName;
myCommand.Parameters.Add("#filetype", SqlDbType.VarChar, 50);
myCommand.Parameters["#filetype"].Value = strfiletype;
myCommand.Parameters.Add("#attachmentID", SqlDbType.VarChar, 50);
myCommand.Parameters["#attachmentID"].Value = strAttachmentID;
myCommand.Parameters.Add("#DateAddedToDB", SqlDbType.DateTime);
myCommand.Parameters["#DateAddedToDB"].Value = DateTime.UtcNow.ToString();
//run sql command
myCommand.ExecuteNonQuery();
//log sql command events
MailboxListener._logging.LogWrite(
"[{0}] Added attachment {1} to database for messageID: {2}",
LoggingLevels.Informational,
System.Reflection.MethodBase.GetCurrentMethod().ToString(),
AttachmentFilename,
strMessageID
);
//if DB is open, close it
if (DbConnection.State == System.Data.ConnectionState.Open)
{
this.DbConnection.Close();
}
}
//catch errors
catch (Exception ex)
{
MailboxListener._logging.LogWrite("[{0}] Error Returned: {1}",
LoggingLevels.Error,
System.Reflection.MethodBase.GetCurrentMethod().ToString(),
ex.Message.ToString());
}
}
No idea why this doesn't work but this code screams for refactoring:
public void AddAttachmentToDB(
XmlNode root,
XmlNamespaceManager xmlns,
string MessageID,
string MailBoxAliasName
)
{
var strMailBoxAliasName = MailBoxAliasName;
var AttachmentFilename = "yumyum";
var AttachmentStream = "Cheetos";
var strMessageID = "123";
var strMailBoxAliasName = "user";
var strfiletype = ".txt";
var strAttachmentID = "12345";
// Use DateTime when working with dates
var dates123 = new DateTime(2011, 2, 3);
try
{
using (var conn = new SqlConnection(DbConnectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = #"INSERT INTO MailboxListenerAttachments Values (#attachmentfilename, #attachmentbody, #messageID, #mailboxname, #filetype, #attachmentID, #DateAddedToDB";
cmd.Parameters.AddWithValue("#attachmentfilename", AttachmentFilename);
cmd.Parameters.AddWithValue("#attachmentbody", AttachmentStream.Trim());
cmd.Parameters.AddWithValue("#messageID", strMessageID);
cmd.Parameters.AddWithValue("#mailboxname", strMailBoxAliasName);
cmd.Parameters.AddWithValue("#filetype", strfiletype);
cmd.Parameters.AddWithValue("#attachmentID", strAttachmentID);
cmd.Parameters.AddWithValue("#DateAddedToDB", dates123);
cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
// TODO: Log the exception and propagate it
throw ex;
}
}
Shouldn't Dates123 be of a DateTime type instead of a string?
I think you need to specify input/output directions for all of the paramters.
for example : myCommand.Parameters["#attachmentfilename"].Direction = ParameterDirection.Input
If you really have no idea you can try
Fix your insert statement so it
explicitly names columns maybe your
ordering is incorrect and insert
statement doesnt work
your setting parameters length to
maximum column length values, maybe you
need to set them to actual parameter
values length
I really think that Dates123 is
indeed the most important problem here, it
should be DateTime not string.
So you changed it but you still call DateTime.UtcNow.ToString() , leave it as DateTime type not string.

Incorrect Syntax near Where for an Update query

Here is the update query which i am using to update a table. It throws me an exception "Incorrect Syntax near Where" Why is that exception for? i have no idea.
public bool UpdateLocationCountintoMerchantPackage(int PackageID, long MerchantID,int LocationCount)
{
try
{
SqlParameter[] parameters = new SqlParameter[]
{
new SqlParameter("#packageID",PackageID),
new SqlParameter("#merchantID",MerchantID ),
new SqlParameter("#locationCount",LocationCount )
};
string CommandText = string.Empty;
CommandText = "Update Merchant_Package SET LocationCount Where MerchantID=#MerchantID";
string ConnectionString = DbConnectionStrings.GetDbConnectionString();
SqlHelper.ExecuteNonQuery(ConnectionString, System.Data.CommandType.Text, CommandText, parameters);
return true;
}
catch (SqlException ex)
{
LogError("Error Occurred When Saving Merchant Location Count Data : MerchantID:" + MerchantID.ToString(), ex);
return false;
}
}
this function is called from
protected void imgbtnSubmit_Click(object sender, ImageClickEventArgs e)
{
UpdatePaymentInfo();
string QueryString = Request.QueryString.ToString();
if (string.Equals(QueryString, "MerchantProfilePages"))
{
Response.Redirect(ApplicationData.URL_ADD_PROFILE_PAGE, false);
Merchant mrchnt = new Merchant();
int PackId = mrchnt.PackageID;
int x = GetLocationCount() + 1;
mrchnt.UpdateLocationCountintoMerchantPackage(PackId, merchantId, x);
}
It's an issue with your "SET LocationCount" - you're not setting it equal to anything. That's why it's complaining about the WHERE.
Use SQL like:
Update Merchant_Package SET LocationCount=#LocationCount
Where MerchantID=#MerchantID
Your error on the 1st line was reported when WHERE was encountered

Categories

Resources