I have a ListBox called listbox. Its "multiple selection" property is set to true. I need to store the selections from this ListBox into a database field.
Note that I am using web forms, ASP.NET, C#, and Visual Studio Web Developer 2010 Express.
My code is as follows:
SqlCommand insertNL = new SqlCommand("insert into dbo.newsletter (newsletter_subject,newsletter_body,newsletter_sentto) VALUES ('" + TextBox1.Text + "', '" + TextBox2.Text + "', '" + ListBox1.SelectedItem + "')", badersql);
badersql.Open();
insertNL.ExecuteNonQuery();
badersql.Close();
Unfortunately, this code only stores the first selected value of the ListBox in the "newsletter_sentto" column of my newsletter table. Does anyone have any suggestions as to how to fix this code? Thanks in advance.
Things to fix:
Before doing anything else, parameterize your sql. This is ripe for injection. Tutorial here.
You aren't disposing of your cmd or connection string. Wrap those in Using clauses. Example here.
Do a foreach on the items to see which ones are selected. Either store those in a comma separated list in the database (which needs parsing on the way back out) or store them in their own table.
You need to decide how you want to store the multiple "newsletter_sentto" values first.
You're best solution is to create a new child table where you have 1 row and column per selected item, with a foreign key back to your newsletter table.
You can try to store them all together in one row with multiple columns (sentto1, sentto2, etc), this will limit the max number of values you can store, and will cause problems searching across multiple fields. How will you query what was sent to a particular person? WHERE sentto1=#user or sentto2=#user... no index can be used there.
You can stuff all the value in a single row and column using a "," or ";" to separate the values. this will cause many problems because you'll have to constantly split the string apart, every time you need to get at one of the sentto values.
First, you should use parametrized queries instead of straight concatenation to protect against SQL injection. Second, you need to cycle through the selected items and build (presumably) a delimited-list of the selections.
var selectedItems = new List<string>();
foreach( var item in ListBox1.SelectedItems )
selectedItems.Add( item.ToString() );
var sql = "Insert dbo.newsletter(newsletter_subject,newsletter_body,newsletter_sentto)"
+ " Values(#newsletter_subject, #newsletter_body, #newsletter_sentto)"
badersql.Open();
using ( qlCommand = new SqlCommand(sql, badersql) )
{
qlCommand.Parameters.AddWithValue("#newsletter_subject", TextBox1.Text);
qlCommand.Parameters.AddWithValue("#newsletter_body", TextBox2.Text);
qlCommand.Parameters.AddWithValue("#newsletter_sentto", string.Join(',', selectedItems.ToArray()));
qlCommand.ExecuteNonQuery();
};
Try to get selected items like that :
string newsletterSentTo = "";
foreach (ListItem item in ListBox1.Items)
{
if (item.Selected)
newsletterSentTo += "," + item.Text;
}
Related
So i'm making a library system, and i encounter a problem in my Borrowing and Returning of books.
When i borrow a book then return it changing the status to return, then borrowing that same book again success, then when i'm returning it my trapping for return books message show.
sql = "SELECT * FROM tbltransactionbooks WHERE fBarCodeNo LIKE '" + txtBARCODE_R.Text.Trim() + "%'";
cfgotcall.engageQuery(sql);
if (cfgotcall.tbl.Rows[0]["fStatus"].ToString().Equals("Borrowed"))
{
txtTITLE_R.Text = cfgotcall.tbl.Rows[0]["fBookTitle"].ToString();
txtAUTHOR_R.Text = cfgotcall.tbl.Rows[0]["fAuthor"].ToString();
txtYEAR_R.Text = cfgotcall.tbl.Rows[0]["fBookYr"].ToString();
txtACCNO_R.Text = cfgotcall.tbl.Rows[0]["fAccNo"].ToString();
txtCALLNO_R.Text = cfgotcall.tbl.Rows[0]["fCallNo"].ToString();
txtBARCODE_BR.Text = cfgotcall.tbl.Rows[0]["fBarcodeNo"].ToString();
txtSEARCH.Text = cfgotcall.tbl.Rows[0]["fStudent"].ToString();
txtReturnDate.Text = cfgotcall.tbl.Rows[0]["fBorrowDate"].ToString();
txtIDNO.Text = cfgotcall.tbl.Rows[0]["fIDStudent"].ToString();
txtLEVEL.Text = cfgotcall.tbl.Rows[0]["fLevel"].ToString();
}
else
{
MessageBox.Show("Book already returned.");
}
What i debug in my own code in the pic is it doesn't scan the whole rows in the tbltransactionbooks it only reads the first row of my table.
33 123 NAME IT 2/20/2017 2/20/2017 [HISTORY OF] COMPUTERS: THE MACHINES WE THINK WITH Returned
33 123 NAME IT 2/21/2017 2/21/2017 [HISTORY OF] COMPUTERS: THE MACHINES WE THINK WITH Borrowed
![2]: http://i66.tinypic.com/28ajgwg.jpg
How dow I scan the whole rows in my table? If my code above does not look good I'm open in suggestion of how I am able make it clean. thanks
cfgotcall.tbl.Rows[0] refers to the the first row only.
You should iterate each row:
sql = "SELECT * FROM tbltransactionbooks WHERE fBarCodeNo LIKE '" + txtBARCODE_R.Text.Trim() + "%'";
cfgotcall.engageQuery(sql);
foreach(var row in cfgotcall.tbl.Rows)
{
if (row["fStatus"].ToString().Equals("Borrowed"))
{
txtTITLE_R.Text = row["fBookTitle"].ToString();
txtAUTHOR_R.Text = row["fAuthor"].ToString();
txtYEAR_R.Text = row["fBookYr"].ToString();
txtACCNO_R.Text = row["fAccNo"].ToString();
txtCALLNO_R.Text = row["fCallNo"].ToString();
txtBARCODE_BR.Text = row["fBarcodeNo"].ToString();
txtSEARCH.Text = row["fStudent"].ToString();
txtReturnDate.Text = row["fBorrowDate"].ToString();
txtIDNO.Text = row["fIDStudent"].ToString();
txtLEVEL.Text = row["fLevel"].ToString();
}
else
{
MessageBox.Show("Book already returned.");
}
}
To avoid getting run time errors due to typos in the column names and the SQL query, you can use LINQ to SQL or Entity Framework. This way each row is converted to an object and you can access each column by accessing an object property\field.
The first row is checked because use access only the first row:
if (cfgotcall.tbl.Rows[0]...)
To check all the rows, iterate through the cfgotcall.tbl.Rows collection either using the for or foreach loop.
You are only accessing the first row [0] of the table. You need to itterate through all of them using for or foreach loop.
Side note: I guess this is a homework. It will not do you any good if you find complete solution in the internet. You should rather try to understand how collections/arrays work and how to traverse them using loops.
A couple of tutorials to help you with the task:
https://msdn.microsoft.com/en-us/library/aa288462(v=vs.71).aspx
http://csharp.net-informations.com/collection/csharp-collection-tutorial.htm
I have a dropdownlist of zipcodes.
It is a really large list and takes too long to load from database. So, first I was looking for the best solution to try and cache or save this data when the website is first loaded so I can use it whenever needed. I tried a list and dictionary then setting the datasource in code behind but it wouldn't let me set the selected value.
It kept telling me that it couldn't bind to a control with no datasource. To make things more difficult the dropdownlist is inside a formview.
I am just not sure the best way to go about this. I am setting the datasource and values in the formview created method but my selected value comes from the formview datasource.
private Dictionary<int, string> CreateZipcodeList()
{
string connStr = ConfigurationManager.ConnectionStrings["KlamathAlgaeEntityDevConnectionString"].ConnectionString;
SqlConnection conn = new SqlConnection(connStr);
Dictionary<int,string> ziplist = new Dictionary<int,string>();
//Create CoreEntity Record
SqlCommand cmd1 = new SqlCommand(#"select zipcode.ZipCodeId, zipcode.zip + ', ' + city.name + ', ' + ISNULL(GeographicState.name,'') + ', ' + Country.name as zipstring
from zipcode left outer join City on ZipCode.CityId = city.CityId
left outer join GeographicState on ZipCode.GeographicStateId = GeographicState.GeographicStateId
left outer join Country on ZipCode.CountryId = Country.CountryId
order by country.name, GeographicState.name, city.name",
conn);
try
{
conn.Open();
SqlDataReader reader = cmd1.ExecuteReader(CommandBehavior.CloseConnection);
while (reader.Read())
{
if (!reader.IsDBNull(0))
{
ziplist.Add(reader.GetInt32(0), reader["zipstring"].ToString());
}
}
}
finally
{
if (conn != null)
{
conn.Close();
}
}
return ziplist;
}
protected void AddressForm_ItemCreated(Object sender, EventArgs e)
{
((DropDownList)AddressForm.FindControl("Zipcodeddl")).DataSource = CreateZipcodeList();
((DropDownList)AddressForm.FindControl("Zipcodeddl")).DataTextField = "Value";
((DropDownList)AddressForm.FindControl("Zipcodeddl")).DataValueField = "Key";
((DropDownList)AddressForm.FindControl("Zipcodeddl")).DataBind();
//((DropDownList)AddressForm.FindControl("Zipcodeddl")).SelectedValue = Eval("zipcodeid").ToString();
}
This populates the dropdown fine but when I try setting the selected value it says the control is not databound. This also doesn't store the dictionary anywhere so I need to call the function to load dictionary when ever I need it.
Ok, that is way too many records for a drop down. Why don't you allow the user to enter 5 numberic characters, and then do an search on your Database by that number. I can't think of any reason you would have to put the entire zip code list in a drop down since no one is going to manually click down to find the one they want. I don't think it servers a usefull purpose, but if there is one let me know and I will try to figure out a solution.
Thats how the post office does it.
Update
To make this work, you would have a TextBox where a user could enter the zip code they think it is. Give them a button to click to search for that zip code.
Do an sql query to your database looking for that Zipcode.Zip, and if found, bring back all the data you need.
If it is not found what I would do is start removing the last character and do another search with a modified query with "Zipcode.Zip like '%modifiedZipCode%', and bring back the closest 10 or so options, and put those in a drop down menu.
If you remove one digit and the database could not find it you could go as far as you want removing characters, and rerunning the query until you got 10 or however many records you want. At some point removing digits will become pointless because the user obviously entered an incorrect zip code.
I know this is very basic, but I can't seem to get it right. I have this datatable that I will fill with processed information from my database.
After searching if the EmpRequestID has already been added in the Datatable, I want to be able to get the value of the column named "RequestedEmp" of the returned row and check if already contains the initials that my variable is currently hosting (it is in a loop). If it does not, append the initials in the variable in the existing initials in the row.
DataRow[] MyEmpReq_Row = MyEmpRequests_DataTable.Select("EmpRequestID='" + EmpRequestID + "'");
int SameReqID = MyEmpReq_Row.Length;
if (MyEmpReq_Row > 0) //REQ ID IN DT, MULTIPLE EMP 1 REQUEST
{
//INSERT HERE
}
else //ID NOT IN DT YET
{
MyEmpRequests_DataTable.Rows.Add(EmpRequestID, ActionBy, Requested_Initials, DateSubmitted, RequestStatus);
}
I want to be able to do something like this
string RetrievedInitials = MyEmpReq_Row["RequestedEmp"].ToString();
if (RetrievedInitials LIKE '%" + Requested_Initials + "'") // but if statements doesnt have LIKE
or this and then know if the column contains the value or not.
MyEmpReq_Row.Select("RequestedEmp LIKE '%" + Requested_Initials + "'");
if (RetrievedInitials.Contains(Requested_Initials))
Take a look at the string class:
http://msdn.microsoft.com/en-us/library/system.string.aspx
As already mentioned by some other posters, the Contains() method may be of use. However, you should also look at EndsWith() (which is more in line with your use of the wildcard in your LIKE query) and StartsWith().
Example:
if (RetrievedInitials.EndsWith(Requested_Initials))
private void Filtriraj()
{
string filter = string.Empty;
if (txtID.Text.Length > 0)
{
filter = "ID LIKE '%" + txtID.Text + "%'";
}
if (txtName.Text.Length > 0)
{
filter = "Name LIKE '%" + txtName.Text + "%'";
}
}
I want to search thru ms access db tables in my c# app. The one above is connected to "Table1" that has some fields like ID, name, surname, address...ID type is set to autonumber, all others are to text. I'm able to search all fields except by ID, this way above wont work, i get exception when i try to search by ID (I type in txtbox some ID number that is in db, exmp: '1')
Search by txtName is working fine.
Autonumber is some form of number (long I think) so you can't use the LIKE keyword. You must search for an exact match (or greather than, less than etc.). You also can't surround a number with single quotes, so those will need to be removed.
I'd switch your code to something like this:
.
.
.
if (txtID.Text.Length > 0)
{
int id;
if (Int32.TryParse(txtID.Text, out id))
{
filter = "ID = " + id.ToString();
}
}
.
.
.
Also, your code looks like it may not work properly if you have multiple text boxes filled with data (because you are not using else if). Whatever text box you check last will end up being the filter that gets used because you're reassigning the filter variable each time. And if you're using the filter text directly from the text boxes, you're opening yourself up to possible SQL Injection. You should probably look into using parameterized queries.
I am trying to make a messagebox text provide datatable results. Below is a snippet of code that I have written so far:
String mystring = comboBox1.Text;
if (mystring.Substring(0, 12) == ("Company Name"))
{
textBox2.Text = mystring.Substring(13);
ADOCon.ConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\Name\Desktop\SmallBizDb.mdb";
ADOCon.Open();
OleDbCommandBuilder CBuilder = new OleDbCommandBuilder(DAdapter);
DAdapter = new OleDbDataAdapter("Select Companies.Company_Name From Companies Where Companies.Company_Name = '" + textBox2.Text + "'", ADOCon);
DAdapter.Fill(DTable);
MessageBox.Show(DTable.ToString());
ADOCon.Close();
ADOCon.Dispose();
}
else
Basically, if an end user types "Company Name-Company One", for example, I would like a message box to appear stating the datatable (DTable) information, which comes from a sql query. Currently, I have "messagebox.Show(DTable.ToString());", which does not work. Also, all other examples I have seen use Row indexes, such as ".Rows[0]", which I cannot use since row numbers are not involved, but rather column names and record names from the sql "where" statement within the data adapter.
There is a lot fluff here, so my major issue is how to convert my datable results so that they will show up in a message box.
Thank you,
DFM
I'm not certain what you are wanting, but if you want to display the values in your datatable you should be able to get the data from it and display it in any order you want. I think you are wanting to do something like
System.Text.StringBuilder b = new System.Text.StringBuilder();
foreach (System.Data.DataRow r in dt.Rows)
{
foreach (System.Data.DataColumn c in dt.Columns)
{
b.Append(c.ColumnName.ToString() + ":" + r[c.ColumnName].ToString());
}
}
MessageBox.Show(b.ToString());
This will loop through all the rows returned, and for each row (each company in the results) add the details in the form ColumnName:ActualValue of the dataTable.
Of course I'm not certain displaying an unknown amount of data in a message box like this is a good idea, that's just a way you can do it.