inserting into data sourced combobox - c#

i am working on visual studio 2012 c# ...
i inserted values into the combox ...i took them from database...I WANT TO KNOW HOW CAN I ADD AN ITEM TO THE COMBOBOX ...ill show u the code below:
Here this function to fill the combobox with names taken from a table in database containig name and id:
List<Lookup> fillCombo(string query, string column)
{
List<Lookup> lookups = new List<Lookup>();
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLConnectionString"].ConnectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand(query, conn);
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Lookup lookupobject = new Lookup();
lookupobject.ID = Convert.ToInt32(reader["ID"]);
//if (reader["Name"] != DBNull.Value)
lookupobject.Name = reader[column].ToString();
lookups.Add(lookupobject);
}
conn.Close();
}
return lookups;
}
then i call this function as follows:
lookups = fillCombo("select id,name from LookupDetails where LOOKUPID = (select id from Lookup where Name = 'users')", "name");
comboBox2.DataSource = lookups;
comboBox2.DisplayMember = "name";

ComboxBox Items collection cannot be modified when the DataSource property is set.
You got the options of either modifying the List<Lookup> or by adding items into combox by iterating over the List<Lookup>.
Here is option to add items in combobox using foreach loop and insert item at 0 index of comboxbox:
lookups = fillCombo(#"select id,name from LookupDetails where LOOKUPID =
(select id from Lookup where Name = 'users')", "name");
foreach(var obj in lookups)
comboBox2.Items.Add(obj);
comboBox2.DisplayMember = "Name";
comboBox2.Items.Insert(0, "");
Note: In the code mentioned in the question, SqlDataReader was never closed, I have modified it by including using statement. You don't have to close SqlDataReader or SqlConnection when you write these in using block:
List<Lookup> fillCombo(string query, string column)
{
List<Lookup> lookups = new List<Lookup>();
string sConstring = ConfigurationManager.ConnectionStrings["SQLConnectionString"].ConnectionString;
using (SqlConnection conn = new SqlConnection(sConstring))
using(SqlCommand cmd = new SqlCommand(query, conn))
{
conn.Open();
using(SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Lookup lookupobject = new Lookup();
lookupobject.ID = Convert.ToInt32(reader["ID"]);
//if (reader["Name"] != DBNull.Value)
lookupobject.Name = reader[column].ToString();
lookups.Add(lookupobject);
}
}
}
return lookups;
}

Related

How to get excel rows one by one in command text using loop?oledb,c#

I am using oledb to read excel file and then i am trying to apply some conditions and then save in db, but i just want to read excel row one by one using loop.
var cmd = conn.CreateCommand();
cmd.CommandText = "select * from [الحيازات$]";// want to get this rows using loop so
//that only specific row is selected perform opertion blow then i will save in db,but
//its selecting all rows now
using (var rdr = cmd.ExecuteReader())
{
//LINQ query - when executed will create anonymous objects for each row
var query = (from DbDataRecord row in rdr
select row)
.Select(x =>
{
//dynamic item = new ExpandoObject();
Dictionary<string, string> item = new Dictionary<string, string>();
for (int i = 0; i < x.FieldCount; i++)
{
//code
}
});
}
Please check this
private void ReadExcel()
{
try
{
string connectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + #";Extended Properties=""Excel 12.0;HDR=YES;IMEX=1;""";
using (OleDbConnection connection = new OleDbConnection())
{
connection.ConnectionString = connectionString;
using (OleDbCommand command = connection.CreateCommand())
{
command.CommandText = "SELECT * FROM [Sheet1$]";
connection.Open();
OleDbDataAdapter dataAdapter = new OleDbDataAdapter(command);
DataSet dataSet = new DataSet();
dataAdapter.Fill(dataSet);
if (dataSet != null && dataSet.Tables[0] != null)
{
foreach (DataRow row in dataSet.Tables[0].Rows)
{
string value = row["EmailColumnName"].ToString();
}
}
}
}
}
catch (Exception ex)
{
//Handle Exception
}
}

SQL query result assertion

I have put together the following method:
public static ArrayList DbQueryToArry()
{
string SqlCString = "connString";
SqlConnection connection = null;
ArrayList valuesList = new ArrayList();
connection = new SqlConnection(SqlCString);
connection.Open();
SqlCommand command = new SqlCommand("Select CLIENTNO, ACCOUNT_Purpose from audit.ACCOUNTS_AUDIT", connection);
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
valuesList.Add(Convert.ToString(reader[0]));
}
return valuesList;
}
I'd like to be able to run an assertion like this one:
var a = DbQueryToArry();
Assert.IsTrue(a.Contains("some value"));
Given reader [0]
valuesList.Add(Convert.ToString(reader[0]));
I only get the first column (CLIENTINFO) into the array and not the second (ACCOUNT_Purpose). How should I modify the code to get both ?
In addition, the returned values could be either a String or Int so would my current code version should be handling both ?
Thanks in advance.
If we switch from obsolete ArrayList to something like IEnumerable<T>:
public static IEnumerable<IDataRecord> DbQueryToArray(string sql) {
if (null == sql)
throw new ArgumentNullException(nameof(sql));
//TODO: do not hardcode connetcion string but read it (say, from Settings)
string SqlCString = "connString";
//DONE: Wrap IDisposable into using
using (SqlConnection connection = new SqlConnection(SqlCString)) {
connection.Open();
//DONE: Wrap IDisposable into using
using (SqlCommand command = new SqlCommand(sql, connection)) {
//DONE: Wrap IDisposable into using
using (SqlDataReader reader = command.ExecuteReader()) {
while (reader.Read()) {
yield return reader as IDataRecord;
}
}
}
}
}
then you can use Linq in order to query the result:
var a = DbQueryToArray("Select CLIENTNO, ACCOUNT_Purpose from audit.ACCOUNTS_AUDIT");
Assert.IsTrue(a.Any(record =>
Convert.ToString(record["CLIENTNO"]) == "some value"));
Assert.IsTrue(a.Any(record =>
Convert.ToString(record["ACCOUNT_Purpose"]) == "some other value"));
If you don't want execute query several times, you can materialize the results:
var a = DbQueryToArray("Select CLIENTNO, ACCOUNT_Purpose from audit.ACCOUNTS_AUDIT")
.ToList();
Assert.IsTrue(a.Any(record => Convert.ToString(record[0]) == "some value"));
Assert.IsTrue(a.Any(record => Convert.ToString(record[1]) == "some other value"));
Finally (see comments below), if we want to test if any field in any record has the value:
var a = DbQueryToArray("Select CLIENTNO, ACCOUNT_Purpose from audit.ACCOUNTS_AUDIT")
.SelectMany(line => {
// Flatten the cursor into IEnumerable<String>
string[] result = new string[line.FieldCount];
for (int i = 0; i < result.Length; ++i)
result[i] = Convert.ToString(line[i]);
return result;
});
a.Any(item => item == "some value");
It is because you only read the first value of the reader. Reader.Read() read each row one by one and Convert.ToString(reader[0])) means that you want to read the first column as string.
That's cause you are getting only the first column. You can do something like below by specifying the column name
while (reader.Read())
{
valuesList.Add(Convert.ToString(reader["CLIENTNO"]));
valuesList.Add(Convert.ToString(reader["ACCOUNT_Purpose"]));
}
Moreover, since you are converting all the columns to string; I would suggest to use a strongly typed collection like List<string> rather then ArrayList valuesList = new ArrayList();
The other answers are good, However some concerns
Lets stop using ArrayList, and use a List<T> instead
Lets use a using statement where you can
Note : I have used a ValueTuple to return more than 1 field
Example
public static List<(string clientNo, string account)> DbQueryToArray()
{
const string SqlCString = "connString";
var valuesList = new List<(string clientNo, string account)>();
using (var connection = new SqlConnection(SqlCString))
{
connection.Open();
using (var command = new SqlCommand("Select CLIENTNO, ACCOUNT_Purpose from audit.ACCOUNTS_AUDIT", connection))
{
var reader = command.ExecuteReader();
while (reader.Read())
valuesList.Add(((string)reader[0],(string)reader[1]) );
}
}
return valuesList;
}
Usage
var results = DbQueryToArray();
Assert.IsTrue(results.Any(x => x.clientNo == someValue || x.account == someValue));
best practice is to check first if the reader has rows
reader.HasRows
then close the reader and the connection
your code should look like this:
public static ArrayList DbQueryToArry()
{
string SqlCString = "connString";
SqlConnection connection = null;
ArrayList valuesList = new ArrayList();
connection = new SqlConnection(SqlCString);
using (connection)
{
connection.Open();
SqlCommand command = new SqlCommand("Select CLIENTNO, ACCOUNT_Purpose from audit.ACCOUNTS_AUDIT", connection);
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
valuesList.Add(Convert.ToString(reader[0]));
valuesList.Add(Convert.ToString(reader[1])); // add to valuelist
}
}
reader.Close(); // close reader
} //dispose connection
return valuesList;
}
Use DataTable and SqlDataAdapter to get query result in form of table. Something like this:
string connString = #"your connection string here";
string query = "select * from table";
DataTable dataTable = new DataTable();
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(query, conn);
conn.Open();
// create data adapter
SqlDataAdapter da = new SqlDataAdapter(cmd);
// this will query your database and return the result to your datatable
da.Fill(dataTable);
conn.Close();
da.Dispose();
Then you can use dataTable object to see if particular values exist.

C# Foreach item in CheckedListBox only gets one item

When I check more than one item in the CheckedListBox, than it only gets the Selected.Value of the last selected item and uses that for the amount of times the foreach is used.
Extra context: It's an application that can put exercises on certain days, so it's a workout app, but when you select more than 1 exercise in the CheckedListBox, than it only adds items with the last selected value.
So selects 3 different items(pushups, pullups, situps) --> 3 situps get added with all the same values.
Code that adds exercises to the other normal ListBox:
query = "INSERT INTO Xercise_Day (DayId, ExerciseId) " +
"VALUES(#DayId, #ExerciseId)";
foreach (CheckedListBox exercise in clbXcercises.CheckedItems)
{
using (connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(query, connection))
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
command.Parameters.AddWithValue("#DayId", scrollBarDays.Value);
command.Parameters.AddWithValue("#ExerciseId", clbXcercises.SelectedValue);
DataTable data = new DataTable();
adapter.Fill(data);
lsBoxDailyX.DataSource = data;
lsBoxDailyX.DisplayMember = "Naam";
}
DailyX();
}
for(int i = 0; i < clbXcercises.Items.Count; i++)
{
clbXcercises.SetItemChecked(i, false);
}
As stated in the comments, reference exercise instead of clbXcercises to get the selected value. The code becomes:
foreach (object exercise in clbXcercises.CheckedItems)
{
using (connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(query, connection))
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
command.Parameters.AddWithValue("#DayId", scrollBarDays.Value);
command.Parameters.AddWithValue("#ExerciseId", exercise.ToString());
DataTable data = new DataTable();
adapter.Fill(data);
lsBoxDailyX.DataSource = data;
lsBoxDailyX.DisplayMember = "Naam";
}
DailyX();
}

Inserting variables as well as columns using SqlBulkCopy

I'm just learning and have written this code to copy data from one database to another (LOTSCON) = source, CON = destination.
The code all works and copies the data across, however it is based on checkboxes on a previous datagridview form.
The user selects which records to import, but also selects CHKCOMMUNITY which means this patient is a nursing home patient.
In the NEW table, there is a column nursinghome which is a bit type.
If the user ticks chkCommunity in the datagrid, I want to do the bulk copy but also make sure the nursinghome column in the destination table is set to 1.
So I'm not mapping an existing column in the source table..
How can I achieve this?
DO I just import then run a SQL string updating the column based on what I have just entered?
foreach (DataGridViewRow row in dataGridInst.Rows)
{
DataGridViewCheckBoxCell chkcell = row.Cells["chkimport"] as DataGridViewCheckBoxCell;
if (chkcell.Value != null)
{
if (Convert.ToBoolean(chkcell.Value) == true)
{
instid = Convert.ToInt32(row.Cells["clninstid"].Value);
iscommunity = Convert.ToInt32(row.Cells["chkcommunity"].Value);
using (SqlConnection lotscon = new SqlConnection(ConfigurationManager.ConnectionStrings["LOTSConnectionString"].ConnectionString))
{
using (SqlCommand cmd = new SqlCommand(#"SELECT Person.*, NEWinstitution.institutionname
FROM NEWinstitution INNER JOIN Person ON NEWinstitution.institutionid = Person.InstitutionID
WHERE person.institutionid = #instid", lotscon))
{
cmd.Parameters.Add("#instid", SqlDbType.Int).Value = instid;
using (SqlDataAdapter adapt = new SqlDataAdapter())
{
adapt.SelectCommand = cmd;
lotscon.Open();
DataSet ds = new DataSet();
adapt.Fill(ds);
DataTable dtgenerate = new DataTable();
dtgenerate = ds.Tables[0];
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString))
{
using (SqlBulkCopy bc = new SqlBulkCopy(con))
{
bc.DestinationTableName = "tblpatient";
bc.ColumnMappings.Add("firstname", "pxfirstname");
bc.ColumnMappings.Add("lastname", "pxlastname");
bc.ColumnMappings.Add("address", "address");
bc.ColumnMappings.Add("suburb", "suburb");
bc.ColumnMappings.Add("medicareno", "medicarenumber");
bc.ColumnMappings.Add("personid", "dispenseid");
bc.ColumnMappings.Add("institutionname", "institutionname");
bc.ColumnMappings.Add("VAcardid", "repatnumber");
bc.ColumnMappings.Add("phonenumber", "phonenumber");
con.Open();
bc.WriteToServer(dtgenerate);
con.Close();
lotscon.Close();
}
}
}
}
}
}
}
}

Binding ComboBox to DataTable (WinForms c#)?

I have a method which populates my ComboBox from a DataTable:
public string populateCompanyTransSellingEntityLookUp(ref System.Windows.Forms.ComboBox Combo, string Id, Contract Contract)
{
SqlCommand _comm = new SqlCommand();
_comm.Parameters.AddWithValue("#id", Id);
_comm.CommandText = "SELECT [name] FROM dbo.fnGetList(#id) ORDER BY [name]; ";
_comm.Connection = _conn;
_comm.CommandTimeout = _command_timeout;
DataTable dt = new DataTable();
try
{
SqlDataReader myReader = _comm.ExecuteReader();
dt.Load(myReader);
Combo.DataSource = dt;
Combo.DisplayMember = "name";
foreach (DataRow dr in dt.Rows)
{
if (dr["name"].ToString() == Contract.Company_Name.ToString())
{
Combo.Text = dr["company_int_name"].ToString();
}
}
}
catch
{
MessageBox.Show("Unable to populate Company Name LookUp");
}
return "";
}
I'm passing my saved value Contract.Company_Name into the forEach loop to find my required SelectedItem from the DataTable. The ComboBox is populated with my DataTable values from Combo.Datasource =dt; but my selected item isn't being set. The code compiles without exception. If I remove Datasource = dt;, theSelectedItemis set no problem. Why is theDatasourceoverriding mySelectedItem` and is there something I've missed with my binding?
Thanks all
At first you have to set the valueMember for sure. Then you can set the selectedValue Property instead of SelectedItem. The Item is one datasource record. So in your case it would be SelectedItem = dr! But iam not sure this is working.
Try this:
Combo.SelectedItem = dr;
I would suggest to use SelectedValue, then you don't need to loop through values "manually".
Also you don't need to use "heavy-weight" DataTable where you need just a collection of string values.
private IEnumerable<string> LoadNames(string id)
{
var query = "SELECT [name] FROM dbo.fnGetList(#id) ORDER BY [name]";
using (var connection = new SqlConnection("connectionString")
using (var command = new SqlCommand(query, connection)
{
// 36 is the size of the VarChar column in database(use your value)
command.Parameters.Add("#id", SqlDbType.VarChar, 36).Value = id;
connection.Open();
using (var reader = command.ExecuteReader())
{
var names = new List<string>();
while(reader.Read())
{
names.Add(reader.GetString(0));
}
return names;
}
}
}
public void Populate(ComboBox combobox, string id, Contract contract)
{
combobox.DataSource = LoadNames(id);
combobox.SelectedValue = contract.Copmpany_Name.ToString();
}
Few things to notice:
Dispose all objects which dealing with external resources (SqlConnection, SqlCommand and SqlDataReader)
Create SqlParameter with precise information about the type, for strings is important to provide size of the column in database. This information will improve SQL query performance on server side.
Don't pass combobox as a reference, populate method does not create new instance but only consume the given ComboBox instance.
Thank you for the help, I edited the code given that my problem was much more trivial.
public string populate_comboBox(ref System.Windows.Forms.ComboBox Combo)
{
SqlCommand _comm = new SqlCommand();
//edited for a simple one column sql query
_comm.CommandText ="SELECT [Column] FROM dbo.SQL_Table ORDER BY [Column];";
//MUST open sql connection to DB
SqlConnection conn = new SqlConnection(global_DB_String_Connection);
conn.Open();
_comm.Connection = conn;
DataTable dt = new DataTable();
try
{
SqlDataReader myReader = _comm.ExecuteReader();
dt.Load(myReader);
Combo.DataSource = dt;
Combo.DisplayMember = "ColumnName";
foreach (DataRow dr in dt.Rows)
{
//populates the combo box with query results
Combo.Text = dr["ColumnName"].ToString();
}
}
catch
{
Console.WriteLine("ComboBox Populate method has failed! ");
}
conn.Close();
return "";
}

Categories