Fill List box with result from stored procedure C# - c#

I have search a bunch for this and as you can tell I'm very new to C#, I I'm trying to learn this language.
So please forgive me if one of the 100 forms that I have looked at says the same thing that you post here.
I am trying to populate a list box with a the results from a stored procedure called LookupInvoices, this requires a parameter #InvoiceNumber that is an int.
I have a WPF that I would like to populate a listbox called lstResults with the results from this stored procedure.
Please look at my code and tell me where I have made an error, thanks so much for your time!
private void btnFill_Click(object sender, RoutedEventArgs e)
{
if (cmbInvoiceNumbers.SelectedItem == null)
{
System.Windows.MessageBox.Show("Please Choose A Invoice Number!");
return;
}
SqlConnection cs = new SqlConnection("Data Source=JAMES-DESKTOP\\SQLEXPRESS;Initial Catalog=contacts;Integrated Security=True");
int cboItemNumber = cmbInvoiceNumbers.SelectedIndex;
int invNumber = Convert.ToInt32(cmbInvoiceNumbers.Items[cboItemNumber].ToString());
cs.Open();
SqlCommand cmd = new SqlCommand("LookupInvoices", cs);
using (SqlDataReader reader = cmd.ExecuteReader())
{
SqlParameter pram = new SqlParameter("#invoiceNumber", invNumber);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(pram);
cmd.Connection = cs;
reader.Read();
}
cs.Close();
}
Please not that when I click the button it crashes. This doesn't run all the way through.

You should put your all disposable elements (SqlConnection, SqlCommand, SqlDataReader) into using (....) { ...... } blocks, and you need to add the parameter before calling .ExecuteReader() - try this code:
public class InvoiceDto
{
public string Description { get; set; }
public int Hours { get; set; }
public decimal Amount { get; set; }
}
public void List<InvoiceDto> GetInvoiceData(int invoiceNumber)
{
List<InvoiceDto> data = new List<InvoiceData>();
using (SqlConnection cs = new SqlConnection("Data Source=JAMES-DESKTOP\\SQLEXPRESS;Initial Catalog=contacts;Integrated Security=True"))
using (SqlCommand cmd = new SqlCommand("dbo.LookupInvoices", cs))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#invoiceNumber", SqlDbType.Int).Value = invoiceNumber;
cs.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
InvoiceDto dto = new InvoiceDto();
dto.Description = reader.GetFieldValue<string>(0);
dto.Hours = reader.GetFieldValue<int>(1);
dto.Amount = reader.GetFieldValue<decimal>(2);
data.Add(dto);
}
}
cs.Close();
}
return data;
}
and in your code-behind, you should call this method in your event handler
private void btnFill_Click(object sender, RoutedEventArgs e)
{
// get selected invoice number
int cboItemNumber = cmbInvoiceNumbers.SelectedIndex;
int invNumber = Convert.ToInt32(cmbInvoiceNumbers.Items[cboItemNumber].ToString());
// call method to get the data from the stored procedure
List<InvoiceDto> data = GetInvoiceData(invNumber);
// loop over the data and fill your listbox
foreach(InvoiceDto dto in data)
{
listbox.Items.Add(dto.Description);
}
}

Related

C# and MySql Procedure

I have 2 tables. Main_items and Help_items.
Main_items has these columns
(main_items_id,main_items_name)
Help_items has these columns
(help_items_id,Help_items_name, main_items_id).
I wrote this Procedure
CREATE DEFINER=`root`#`localhost` PROCEDURE `thamer1`(in main_items_id_ int,
out res int)
BEGIN
declare a int;
declare b int;
select count(help_items_id)
into a from help_items
where main_items_id=main_items_id_;
if a=0 then
set b=(main_items_id_*10)+1;
set res=b;
else
select COALESCE(max(help_items_id),0)+1
into res
from help_items
where main_items_id=main_items_id_;
end if;
END
This procedure works with MySql WrokBench.
And this for c# code
private void a_KeyDown(object sender, KeyEventArgs e)
{
using (MySqlConnection mysqlcon6 = new
MySqlConnection(connectString))
{
mysqlcon6.Open();
MySqlCommand mysqlcmd6 = new MySqlCommand("thamer1", mysqlcon6);
mysqlcmd6.CommandType = CommandType.StoredProcedure;
mysqlcmd6.CommandText = "thamer1";
mysqlcmd6.Parameters.Add("#main_items_id_", MySqlDbType.Int32).Value = a.Text;
mysqlcmd6.Parameters.Add("#res", MySqlDbType.Int32).Value=HITEM.Text;
mysqlcmd6.ExecuteNonQuery();
// MessageBox.Show("saved");
// GridFill();
}
}
I select value (for main_items_id) from DataGrideView and fetch it into textbox named a.
When I press ENTER I get this Message
System.FormatException:' Input string was not in a correct format'
I hope to help me to solve this error.
Remove the portion of this line that sets the parameter value:
mysqlcmd6.Parameters.Add("#res", MySqlDbType.Int32).Value=HITEM.Text;
It looks like you expect that to bind the result of #res to the HITEM textbox, and that's not what happens. HITEM.Text is just a string, and when you assign that value to an int parameter, you're telling MySql you expect it to be able to parse that string into an int.
Instead, only create the parameter, like this:
mysqlcmd6.Parameters.Add("#res", MySqlDbType.Int32);
You also need to tell ADO.Net this is an OUTPUT parameter. Then check the parameter value after the query runs by assigning the parameter value to HITEM.Text rather than from HITEM.Text:
private void a_KeyDown(object sender, KeyEventArgs e)
{
//You can re-use the *names* of these variables, since their scopes are limited to the method
//You can also stack them to share the same scope block and reduce nesting/indentation
using (var con = new MySqlConnection(connectString))
using (var cmd = new MySqlCommand("thamer1", con))
{
cmd.CommandType = CommandType.StoredProcedure;
// mysqlcmd6.CommandText = "thamer1"; //you already did this in constructor. Don't need to do it again
cmd.Parameters.Add("#main_items_id_", MySqlDbType.Int32).Value = a.Text;
//DON'T assign to the Value, but DO make sure ADO.Net understands this is an OUTPUT parameter
cmd.Parameters.Add("#res", MySqlDbType.Int32).Direction = ParameterDirection.Output;
//wait as long as possible to call Open()
con.Open();
cmd.ExecuteNonQuery();
//Now you can assign **to** HITEM.Text, rather than from it.
HITEM.Text = cmd.Parameters["#res"].Value;
}
//End the scope as soon as possible, so the connection can be disposed faster
// MessageBox.Show("saved");
// GridFill();
}
And here it is again without all the extra comments:
private void a_KeyDown(object sender, KeyEventArgs e)
{
using (var con = new MySqlConnection(connectString))
using (var cmd = new MySqlCommand("thamer1", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#main_items_id_", MySqlDbType.Int32).Value = a.Text;
cmd.Parameters.Add("#res", MySqlDbType.Int32).Direction = ParameterDirection.Output;
con.Open();
cmd.ExecuteNonQuery();
HITEM.Text = cmd.Parameters["#res"].Value;
}
}
Even better practice would move all your SQL methods to a separate class, away from your event handlers. The event handlers should only need to call methods in the new class, like this:
public static class DB
{
private static string connectionString = "...";
public static int thamer(int main_item_id)
{
using (var con = new MySqlConnection(connectString))
using (var cmd = new MySqlCommand("thamer1", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#main_items_id_", MySqlDbType.Int32).Value = main_item_id;
cmd.Parameters.Add("#res", MySqlDbType.Int32).Direction = ParameterDirection.Output;
con.Open();
cmd.ExecuteNonQuery();
return (int)cmd.Parameters["#res"].Value;
}
}
}
private void a_KeyDown(object sender, KeyEventArgs e)
{
HITEM.Text = DB.thamer(int.Parse(a.Text)).ToString();
}
Change this
mysqlcmd6.Parameters.Add("#main_items_id_",
MySqlDbType.Int32).Value = a.Text;
mysqlcmd6.Parameters.Add("#res", MySqlDbType.Int32).Value =
HITEM.Text;
to
int value1 = 0;
int value2 = 0;
if (!Int32.Text.TryParse(a.Text) || !Int32.TryParse(HITEM.Text))
{
return;
}
mysqlcmd6.Parameters.Add("#main_items_id_", MySqlDbType.Int32).Value = value1;
mysqlcmd6.Parameters.Add("#res", MySqlDbType.Int32).Value = value2;

C# asp.NET displaying output of a query to screen. Error: 'System.ArgumentException' in Oracle.DataAccess.dll

First post here. I'm trying to create a website that fetches data from an Oracle database and returns some tables. I was able to connect my database fine and made a DataConnector that returns a list of CodeDesc objects. My main problem right now is simply displaying that data to the screen, preferably in the form of a drop down list but I'm using a GridView for now.
Here's my front end:
protected void Button1_Click(object sender, EventArgs e)
{
DataConnector dc = new DataConnector();
GridView2.DataSource = dc.getCodeTypes();
GridView2.DataBind();
}
When I click the button, nothing is generated and the debugger only says "Exception thrown: 'System.ArgumentException' in Oracle.DataAccess.dll" Any help would be appreciated. This is my first time doing web development and it's been a struggle to get even this far. I'm using Visual Studio 2015
Back End:
//Create datatable to get info from db & return results
public List<CodeDesc> getCodeTypes()
{
try
{
OracleConnection con = new OracleConnection(connString);
con.Open();
string query = "select id, descr from code_desc where code_type_id = 0";
// Create the OracleCommand
OracleCommand cmd = new OracleCommand();
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
// Execute command, create OracleDataReader object
OracleDataReader reader = cmd.ExecuteReader();
List<CodeDesc> L = new List<CodeDesc>();
while (reader.Read())
{
CodeDesc c = new CodeDesc();
c.id = reader.GetInt32(0);
c.description = reader.GetString(1);
L.Add(c);
}
// Clean up
reader.Dispose();
cmd.Dispose();
con.Dispose();
System.Diagnostics.Debug.WriteLine(L);
return L;
}
catch (Exception ex)
{
// catch clause here...
}
}
CodeDesc:
public class CodeDesc
{
public int id { get; set; }
public string description { get; set; }
}
Any help would be great.
You never set the query string to the CommandText property of the OracleCommand. Of course this can only result in an exception when you try to execute your command.
Said that, remember that every disposable object should be enclosed in a using statement. This is very important in case of exceptions because the correct closing and disposing is executed automatically exiting from the using block
public List<CodeDesc> getCodeTypes()
{
try
{
List<CodeDesc> L = new List<CodeDesc>();
string query = "select id, descr from code_desc where code_type_id = 0";
using(OracleConnection con = new OracleConnection(connString))
using(OracleCommand cmd = new OracleCommand(query, con))
{
con.Open();
// Execute command, create OracleDataReader object
using(OracleDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
CodeDesc c = new CodeDesc();
c.id = reader.GetInt32(0);
c.description = reader.GetString(1);
L.Add(c);
}
}
}
System.Diagnostics.Debug.WriteLine(L);
return L;
}

get all row and column data using SELECT - C#

I'm trying to get all data from an SQL table and store it in a List using the C# programming language.
the SQL statement I'm using is:
private string cmdShowEmployees = "SELECT * FROM Employees;";
This is being used in the same class as a function
public List<string> showAllIdData()
{
List<string> id = new List<string>();
using (sqlConnection = getSqlConnection())
{
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandText = cmdShowEmployees;
SqlDataReader reader = sqlCommand.ExecuteReader();
while (reader.Read()) {
id.Add(reader[0].ToString());
}
return id;
}
}
and here
public List<string> showAllActiveData()
{
List<string> active = new List<string>();
using (sqlConnection = getSqlConnection())
{
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandText = cmdShowEmployees;
SqlDataReader reader = sqlCommand.ExecuteReader();
while (reader.Read()) {
active.Add(reader[1].ToString());
}
return active;
}
I would have to create 9 more functions this way in order to get all the data out of the Employees table. This seems very inefficient and I was wondering if there was a more elegant way to do this.
I know using an adapter is one way to do it but I don't think it is possible to convert a filled adapter to a list, list list etc.
SqlDataAdapter adapter = sqlDataCollection.getAdapter();
DataSet dataset = new DataSet();
adapter.Fill(dataset, "idEmployees");
dataGridView1.DataSource = dataset;
dataGridView1.DataMember = "idEmployees";
Any ideas?
If you must use the reader in this way, why not create an object which holds the table row data.
public class SomeComplexItem
{
public string SomeColumnValue { get; set;}
public string SomeColumnValue2 { get; set;}
public string SomeColumnValue3 { get; set;}
public string SomeColumnValue4 { get; set;}
}
That way you can loop through with your reader as follows:
public List<SomeComplexItem> showAllActiveData()
{
List<SomeComplexItem> active = new List<SomeComplexItem>();
using (sqlConnection = getSqlConnection())
{
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandText = cmdShowEmployees;
SqlDataReader reader = sqlCommand.ExecuteReader();
while (reader.Read())
{
var someComplexItem = new SomeComplexItem();
someComplexItem.SomeColumnValue = reader[1].ToString();
someComplexItem.SomeColumnValue2 = reader[2].ToString();
someComplexItem.SomeColumnValue3 = reader[3].ToString();
active.Add(someComplexItem);
}
return active;
}
You could use two select statements to populate two List<string> as shown in the example below where the key between reads is reader.NextResult();.
The database used is the standard Microsoft NorthWind database.
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
namespace SQL_Server_TwoList
{
public class DataOperations
{
public List<string> Titles { get; set; }
public List<string> Names { get; set; }
/// <summary>
/// Trigger code to load two list above
/// </summary>
public DataOperations()
{
Titles = new List<string>();
Names = new List<string>();
}
public bool LoadData()
{
try
{
using (SqlConnection cn = new SqlConnection(Properties.Settings.Default.ConnectionString))
{
string commandText = #"
SELECT [TitleOfCourtesy] + ' ' + [LastName] + ' ' + [FirstName] As FullName FROM [NORTHWND.MDF].[dbo].[Employees];
SELECT DISTINCT [Title] FROM [NORTHWND.MDF].[dbo].[Employees];";
using (SqlCommand cmd = new SqlCommand(commandText, cn))
{
cn.Open();
SqlDataReader reader = cmd.ExecuteReader();
// get results into first list from first select
if (reader.HasRows)
{
while (reader.Read())
{
Names.Add(reader.GetString(0));
}
// move on to second select
reader.NextResult();
// get results into first list from first select
if (reader.HasRows)
{
while (reader.Read())
{
Titles.Add(reader.GetString(0));
}
}
}
}
}
return true;
}
catch (Exception)
{
return false;
}
}
}
}
Form code
namespace SQL_Server_TwoList
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
DataOperations dataOps = new DataOperations();
if (dataOps.LoadData())
{
listBox1.DataSource = dataOps.Names;
listBox2.DataSource = dataOps.Titles;
}
}
}
}
You could always add it all to a dataset or datatable instead of looping through using datareader to add to an array, dataset allows you to access data in similar way to array anyway.
Connstr = "Data Source = " + SelectedIP + "; Initial Catalog = " + dbName + "; User ID = " + txtUsername.Text +"; Password = "+ txtPassword.Text +"";
conn = new SqlConnection(Connstr);
try
{
string contents = "SELECT * FROM ..."
conn.Open();
SqlDataAdapter da_1 = new SqlDataAdapter(contents, conn); //create command using contents of sql file
da_1.SelectCommand.CommandTimeout = 120; //set timeout in seconds
DataSet ds_1 = new DataSet(); //create dataset to hold any errors that are rturned from the database
try
{
//manipulate database
da_1.Fill(ds_1);
if (ds_1.Tables[0].Rows.Count > 0) //loop through all rows of dataset
{
for (int i = 0; i < ds_1.Tables[0].Rows.Count; i++)
{
//rows[rownumber][column number/ "columnName"]
Console.Write(ds_1.Tables[0].Rows[i][0].ToString() + " ");
}
}
}
catch(Exception err)
{}
conn.Close();
}
catch(Exception ex)
{}

execute reader doesn't respond

i have a php code.here is the code,i gonna to translate it to .NET but in some point i'm getting some trouble.
function processInput($conn, $MessageArray, $mobilenumber, $date, $odd)
{
$strSQLUSER="SELECT * FROM tbl_tiduser WHERE username='".addslashes($MessageArray[0])."' AND stat!='1' AND stat!='4'";
$result_user=odbc_exec($conn,$strSQLUSER) or die("Could not connect to database");
here is the converted .NET code
public class ProcessInput
{
private string msg_arr;
private string MooseSeenInput(string MobileNo,string Date,string odd,params Array[] msg_arr)
{
SqlCommand com = new SqlCommand("SELECT * FROM tbl_tiduser WHERE username=#username AND stat!='1' AND stat!='4'", mycon);
com.Parameters.AddWithValue("#username",username);
using (SqlDataReader reader = com.ExecuteReader())
// whats the next part need to come here ???
}
this is incomplete.i'm not going to compile it....
private static void ReadOrderData(string connectionString)
{
string queryString =
"SELECT OrderID, CustomerID FROM dbo.Orders;";
using (SqlConnection connection =
new SqlConnection(connectionString))
{
SqlCommand command =
new SqlCommand(queryString, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
// Call Read before accessing data.
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}",
reader[0], reader[1]));
}
// Call Close when done reading.
reader.Close();
}
}
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.aspx
I would use something like this to get the column(s) you're after:
string username = null;
using (SqlDataReader reader = com.ExecuteReader()) {
if (reader.read()) {
username = (string)reader["mydbcolumnname"];
}
reader.Close();
}
Note that if you want to pull all the result rows (as opposed to stepping through them) then you'd normally use a SqlDataAdapter to fill a DataSet (instead of the reader), eg:
string username;
using (SqlDataAdapter adapter = new SqlDataAdapter(com))
{
using (DataSet ds)
{
adapter.Fill(ds);
username = (string)ds.Tables[0].Rows[0]["mycolumnname"];
}
}
I'm all for easy; I would write a class that mirrors the record I'm reading, i.e.
public class User {
public int Id {get;set;}
public string Name {get;set;}
}
and use "dapper":
var user = myCon.Query<User>(
"SELECT * FROM tbl_tiduser WHERE username=#username AND stat not in ('1','4')",
new {username}).SingleOrDefault();
if(user == null) { /* not found, presumably throw an exception */ }
string name = user.Name; // etc
Then you don't need to mess with commands, readers, parameters etc (see how the username is being made into a db parameter cleanly?).

C#: help return dataset and assign values to controls

I'm not really used to C# sharp but have used VB.NET before.
I'm needing to set the value of text fields, dropdowns etc from data from a query. To enter the data I have been using a class Computer with the method saveComputer() that takes values from user controls. Now I want an edit page that uses the id from url & uses getComputer(id) from Computer class and returns the values to be set to the user controls. I'm unsure about using this method to set the control values.
Edit.aspx.cs
protected void btnSave_Click(object sender, EventArgs e)
{
int id = 3; //will be replaced to GET value
Computer comp = new Computer();
//comp.updateComputer(ref id);
}
My Computer class
public getComputer(ref int id)
{
DataSet data = new DataSet();
using (SqlConnection conn = new SqlConnection(
"Server=JURA;Database=ReadyForSeven;User id=;Password="))
{
String sql = "SELECT * FROM computers WHERE id=#id";
//replace contatenation of variable with parameter name
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = sql.ToString();
cmd.CommandType = CommandType.Text;
//Define SqlParameter object and assign value to the parameter
cmd.Parameters.Add("#id", SqlDbType.Int);
cmd.Parameters["#id"].Value = id;
try
{
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(data);
// return data here
}
}
catch (SqlException ex)
{
//send user to error page and log message
}
}
}
So what I'm wanting to achieve is using the getcomputer method of Computer to set the values of the controls on Edit.aspx
Can anyone help me out?
You'll need to modify your getComputer method to return a DataSet like:
public DataSet getComputer(int id) {
Once that's done we can call it and populate the form controls on the page load with something like:
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
int id = 3; // get from querystring
DataSet ds = getComputer(id);
DataRow dr = ds.Tables[0].Rows[0]; // get the first row returned
// populate form controls
txtFirstName.Text = dr["FirstName"].ToString();
ddlState.SelectedValue = dr["State"].ToString();
}
}
Below is an updated version of getComputer that will always return a value and is a little tighter:
public DataSet getComputer(int id) // you don't need to pass int by ref unless you're planning on changing it inside this method
{
DataSet data = new DataSet();
using (SqlConnection conn = new SqlConnection("Server=JURA;Database=ReadyForSeven;User id=;Password=")) {
using (SqlCommand cmd = new SqlCommand("SELECT * FROM computers WHERE id = #id", conn)) {
cmd.Parameters.AddWithValue("id", id);
using (SqlDataAdapter da = new SqlDataAdapter(cmd)) {
da.Fill(data);
return data;
}
}
}
}
I had to remove the try/catch blog to ensure the method always returned a value. If you absolutely need the try/catch block you'll need to return an empty DataSet at the end of the method to get to compile correctly.

Categories

Resources