How to display data from mysql and display it one by one? - c#

I have a data in mysql and I want to display the data one by one everytime I click the button. How to do it?
string ConnectToServer = #"server=..*.;port=****; user id=sampleID; password=samplePW; database=sampleDB; pooling=false";
public void GetNames()
{
MySqlConnection NameConnector = null;
MySqlDataReader NameReader = null;
try
{
NameConnector = new MySqlConnection(ConnectToServer);
NameConnector.Open();
string Name = "SELECT * from sampleNames";
MySqlCommand NameCommand = new MySqlCommand(Name, NameConnector);
NameReader = NameCommand.ExecuteReader();
while (NameReader.Read())
{
Console.WriteLine(NameReader.GetInt32(0) + ": " + NameReader.GetString(1));
NameLabel.Text += NameReader.GetString("Names") + "\n";
}
}
catch (MySqlException NameException)
{
Console.WriteLine("error : (0)", NameException.ToString());
}
finally
{
if (NameReader != null)
{
NameReader.Close();
}
if (NameConnector != null)
{
NameConnector.Close();
}
}
}
private void ButtonName_Click(object sender, EventArgs e)
{
GetNames();
}
the output:
Name1
Name2
Name3
Name4
Name5
but I wan't is, the Name will appear one by one each time I click the button
like this:
click = output Name1
click = output Name2
click = output Name3
click = output Name4
click = output Name5

There are at least 2 ways of doing that depending on how real-time you need the data and how many DB calls do you want to make. here they are:
Option #1
Initialize a class level variable for names list and an index variable.
List<string> names = null;
int currentNameIndex = 0;
on the click handler, if names is null, populate the names variable with all names in the DB. display the first item as follows.
private void ButtonName_Click(object sender, EventArgs e)
{
if (names == null)
{
names = GetNames();
}
if (currentNameIndex < names.Count)
{
NameLabel.Text += names[currentNameIndex++];
}
}
the getnames need to be modified to return the list of names.
Option #2
Instead of retrieving the whole list in 1 DB call, you could change the SQL query to get the first record from the Table. (based on a Id or some key)
On a click, GetNames will retrieve only 1 record and display that.
On the next click it'll retrieve another record, but not the first ones.
This would typically involve a query involving a key column. Please post your table schema and I can answer with the Query.
an e.g. Query is
int currentNameId = -1; // class level variable.
query is
Select TOP 1 nameId, names from SampleNames Where NameId > currentNameId Order By NameId;
currentNameId = int.Parse(NameReader[nameId].ToString());
the above query assumes that nameId is a unique key and that values start from 0 or greater than -1, and that they are incremental. (identity PKs etc.)
as I mentioned, if you can provide the table structure, we can answer better.
Option #1 is efficient in DB calls but may potentially have stale data.
Option #2 is more chatty but has more real-time data than Option #1.

You are reading all records:
while (NameReader.Read())
If you want to read just one, try put all your connection outside the method and run
NameReader = NameCommand.ExecuteReader();
only once.
Then change
while (NameReader.Read())
to
NameReader.Read()

Related

Creating a search function in c#, windows form application

I am creating a program as part of a college assignment and must have a database connected to my program. The program is in c# and created in a windows form application with visual studio.
I need to have a text box that allows entry and then a button to search for any values that match that, but I cannot figure out how to read what is inputted, search the database and return them in the text boxes.
I already have the database connected and all of the forms designed and connected together with buttons, however this one part is really baffling me. Any help would be appreciated.P.S I am new to c# and do not fully understand it yet.
Please Take Reference from this link your Answer(along with Database Queries) and Explanation is available
Reference 1
Reference 2
1) Put all the texts from the database in some kind of collection (List for example).
2) Get the text from the textbox by accessing the textbox's Text property. Apply some modifications if you want, such as removing caps, handling keywords etc.
3) Write a linq query that goes something like collection.Where(t => t.Contains(searchString)).ToList(). Alternatively, you can loop over the collection.
4) Feed the resulting list to your output textbox.
In my case, I was used a dataGridView for the DataSet of mysql data and below is the sample code for searchbox.
private void tfSearch_TextChanged(object sender, EventArgs e)
{
if(string.IsNullOrEmpty(tfSearch.Text) == false)
{
dataGridView1.Rows.Clear();
for(int i = 0; i < GlobalState.Items.Tables[0].Rows.Count; i++)
{
string id = GlobalState.Items.Tables[0].Rows[i].ItemArray.GetValue(0).ToString();
string name = GlobalState.Items.Tables[0].Rows[i].ItemArray.GetValue(1).ToString();
string price = GlobalState.Items.Tables[0].Rows[i].ItemArray.GetValue(2).ToString();
string stock = GlobalState.Items.Tables[0].Rows[i].ItemArray.GetValue(3).ToString();
if (name.StartsWith(tfSearch.Text))
{
int index = dataGridView1.Rows.Add();
dataGridView1.Rows[index].Cells[0].Value = id;
dataGridView1.Rows[index].Cells[1].Value = name;
dataGridView1.Rows[index].Cells[2].Value = price;
dataGridView1.Rows[index].Cells[3].Value = stock;
}
}
}
else if(tfSearch.Text == "")
{
dataGridView1.Rows.Clear();
for (int i = 0; i < GlobalState.Items.Tables[0].Rows.Count; i++)
{
string id = GlobalState.Items.Tables[0].Rows[i].ItemArray.GetValue(0).ToString();
string name = GlobalState.Items.Tables[0].Rows[i].ItemArray.GetValue(1).ToString();
string price = GlobalState.Items.Tables[0].Rows[i].ItemArray.GetValue(2).ToString();
string stock = GlobalState.Items.Tables[0].Rows[i].ItemArray.GetValue(3).ToString();
int index = dataGridView1.Rows.Add();
dataGridView1.Rows[index].Cells[0].Value = id;
dataGridView1.Rows[index].Cells[1].Value = name;
dataGridView1.Rows[index].Cells[2].Value = price;
dataGridView1.Rows[index].Cells[3].Value = stock;
}
}
Your Welcome.
Get the textbox text when you click on the button then start a query with that search word so youll get back everything what contains that word
Get input text
Textboxname.text;
Query
SELECT * ON table WHERE tagoridorwhatever = textboxname.text
The query part may be a bit different since im weiting this out of my head on a mobile phone

Using RDLC subreport multiple times

I have a report that lists off taxes for a store given a storeID, a fromDate, and a toDate. I want to use this report as a subreport multiple times in the same parent report. For example, if you use storeID's 1,2,3,4,5 you would have this subreport show 5 times, with the first one having data for store 1, second one having data for store 2, etc.
Is this even possible? I've found some forums where people are asking how to use the same subreport twice in a report, but the threads always die out before they find something. I also saw you can use parameters but I'm not sure how those work (a bit new to sub-reporting in RDLC).
Thanks!
If I understand correctly, probably you can use a single SubReport containing a Table displaying taxes grouped by store.
In the main report, use 5 instances of the subreport.
Change the (Name) property of each subreport, but keep the subreport path the same (as you already did).
When processing the main report, the method LocalReport_SubReportProcessing called many times according to instances count of the subreport found.
You'll make a global variable keeps the current store Id as in the code sampel below.
public class TaxDetailsOfStore
{
public int StoreId { get; set; }
// Your other details here...
}
// This global property be filled for all stores before displaying the main report.
private List<TaxDetailsOfStore> TaxDetailsOfAllStores { get; set; }
private int _storeId = 1; // To start with.
private const int _maxStoreId = 5;
private void LocalReport_SubReportProcessing(object sender, SubreportProcessingEventArgs e)
{
string reportDataSourceName = string.Empty;
object reportDataSourceValue = null;
switch (e.ReportPath)
{
case "SubRprtTaxDetailsOfStore":
int storeId = Convert.ToInt32(e.Parameters["storeId"].Values[0]);
var lstTaxDetailsOfStore = TaxDetailsOfAllStores.FindAll(x => x.StoreId == storeId);
//-------------------------------------------------------------------------------------
// Increment the variable _storeId till reaches _maxStoreId and then back again from 1.
_storeId = _storeId++ % _maxStoreId;
//-------------------------------------------------------------------------------------
reportDataSourceName = "TaxDetailsOfStoreDataSet";
reportDataSourceValue = lstTaxDetailsOfStore;
break;
// Handle other sub reports like this.
//case "SubRprtAnother1":
// object dsSubRprtAnother1 = null;
// reportDataSourceName = "AnotherDataSetName1";
// reportDataSourceValue = dsSubRprtAnother1;
// break;
//case "SubRprtSummary":
// object dsSubRprtSummary = null;
// reportDataSourceName = "SubRprtSummaryDataSet";
// reportDataSourceValue = dsSubRprtSummary;
// break;
}
ReportDataSource reportDataSource = new ReportDataSource
{
Name = reportDataSourceName,
Value = reportDataSourceValue
};
e.DataSources.Add(reportDataSource);
}

How To Save Multiple ListBox Value in a single row and in a single column

I want to save multiple list box value into a single field of a table using linq to entity. this is my code. any suggestion?
protected void Button5_Click(object sender, EventArgs e)
{
for(var i = 0; i < lb2.Items.Count; i++)
{
var e1 = new employee() { emp_skill = lb2.Items[i].Text };
je.employee.AddObject(e1);
}
je.SaveChanges();
}
I assume your data is collection of string and you want to save it as single string. The following code make those collection of string become single string separated by semicolon, then you can save it as single row single column data:
protected void Button5_Click(object sender, EventArgs e)
{
var semicolonSeparatedString = "";
var e1 = (from emp in je.employee where emp.emp_email == txtmail.Text select emp).FirstOrDefault();
for (int index = 0; index < lb2.Items.Count; index++)
{
//no need to add separator for the first item
if (index == 0) semicolonSeparatedString += lb2.Items[index];
else semicolonSeparatedString += ";" + lb2.Items[index];
}
//data formatted as single string and ready to be saved
e1.emp_skill = semicolonSeparatedString;
je.SaveChanges();
And when you want to get it back as collection of string simply use Split() extension method :
//load data from datasource (database or file)
var semicolonSeparatedString = je.employee.FirstOrDefault(o => o.name == "employeeName").Select(o => o.emp_skill);
//split to get the single string data back to array of string
var items = semicolonSeparatedString.Split(';');
foreach(var item in items)
{
lb2.Items.Add(item);
}
I tested the code with ListBox in windows form.
UPDATE :
I update the code to include saving and loading data from database, those parts are untested. My code based on yours in question and several assumptions.
You will need to serialize the values to a single byte stream, then save that data into the database. There are many ways to serialize values, for example binary serialization or XML serialization or any custom serialization mechanism. You are supposed to change the type of the column accordingly (for example, for binary serialization the BLOB-type of your database would be best-suited).

Entity framework inserts wrong entity into db on savechanges

I am trying to write a program to scan a directory containing tv show folders, look up some details about the shows using tvrage API and then save the details to a database using entity framework.
My TVShow table pkey is the same value as taken from the tvrage database show id, and I am having issues when duplicate or similar folder names are returning the same Show info. In a situation where I have a directory containing three folders, "Alias", "Alias 1" , "Band of Brothers" I get the following output from my code
* TV SHOWS *
Alias....... NO MATCH......ADDING........DONE
Alias 1 ...... NO MATCH.....ADDING....CANT ADD, ID ALREADY EXISTS IN DB
Band of Brothers ...... NO MATCH..ADDING....
Before getting an UpdateException on the context.SaveChanges(); line
Violation of PRIMARY KEY constraint 'PK_TVShows'.
I can see using SQL profiler that the problem is that my app is trying to perform an insert on the alias show for a second time with duplicate key, but I can't see why. When I step through the code on the second interaction of the foreach loop (second "alias" folder), the code to save the show entity to the database is bypassed.
It is only on the next iteration of the foreach loop when I have created a new TVShow entity for "Band of Brothers" do I
actually reach the code which adds a Tvshow to context and saves, at which point the app crashes. In visual studio I can see
at the point of the crash that;
"show" entity in context.TVShows.AddObject(show) is "Band of Brothers" w/ a unique ID
context.TVShows only contains one record, the first Alias Entity
But SQL profiler shows that EntityFramework is instead inserting Alias for a second time, and I am stumped by why this is
private void ScanForTVShowFolders( GenreDirectoryInfo drive ) {
IEnumerable<DirectoryInfo> shows = drive.DirInfo.EnumerateDirectories();
foreach (DirectoryInfo d in shows) {
//showList contains a list of existing TV show names previously queried out of DB
if (showList.Contains(d.Name)) {
System.Console.WriteLine(d.Name + ".....MATCH");
} else {
System.Console.Write(d.Name + "......NO MATCH..ADDING....");
TVShow show = LookUpShowOnline(d.Name, drive.GenreName);
if (show.Id == -1) { // id of -1 means online search failed
System.Console.Write("..........CANT FIND SHOW" + Environment.NewLine);
} else if (context.TVShows.Any(a => a.Id == show.Id)) { //catch duplicate primary key insert
System.Console.Write(".......CANT ADD, ID ALREADY EXISTS IN DB" + Environment.NewLine);
} else {
context.TVShows.AddObject(show);
context.SaveChanges();
System.Console.Write("....DONE" + Environment.NewLine);
}
}
}
private TVShow LookUpShowOnline( string name, string genre ) {
string xmlPath = String.Format("http://services.tvrage.com/feeds/search.php?show='{0}'", name);
TVShow aShow = new TVShow();
aShow.Id = -1; // -1 = Can't find
XmlDocument xmlResp = new XmlDocument();
try { xmlResp.Load(xmlPath); } catch (WebException e) { System.Console.WriteLine(e); }
XmlNode root = xmlResp.FirstChild;
if (root.NodeType == XmlNodeType.XmlDeclaration) { root = root.NextSibling; }
XmlNode tvShowXML;
//if (showXML["episode"] == null)
// return false;
tvShowXML = root["show"];
if (tvShowXML != null) {
aShow.Id = System.Convert.ToInt16(tvShowXML["showid"].InnerText);
aShow.Name = tvShowXML["name"].InnerText.Trim();
aShow.StartYear = tvShowXML["started"].InnerText.Trim();
aShow.Status = tvShowXML["status"].InnerText.Trim();
aShow.TVGenre = context.TVGenres.Where(b => b.Name.Trim() == genre).Single();
}
return aShow;
}
}
Edit
Doing some more reading I added context.ObjectStateManager to my debug watchlist and I can see everytime I create a new TVShow entity a new record is added to _addedEntityStore. Actually if I remove context.TVShows.AddObject(show) the code still updates the database so manually adding to the context seems redundant.
If your are inserting object by foreach loop > better to keep the Primary Key outside and make it increment!
eg: int newID= Shows.Select(d=>d.Id).Max();
foreach(............)
{
show.Id = newID++;
.
.
. //remaining fields
.
context.TVShows.AddObject(show);
}
context.SaveChanges();
it works for me...!!
Turns out context.TVShows.AddObject(show) is unnecessary in my case, I was inadvertently adding all created show entities to the context when this query runs
aShow.TVGenre = context.TVGenres.Where(b => b.Name.Trim() == genre).Single();
This is not what I wanted, I just wanted to create the object, then decide whether to add it. Will be pretty easy to fix now I know why it's happening.

Need help in using MySqlTransaction

Hi all i would like to use MySqlTransaction in my requirement. Actually i am having a doubt regarding that i.e as per my requirement i will have to delete different values from database.
The process i am doing is as follows. Assume that i am having 2 EmpIDs where this EmpID will hold different values which may be multiple. I will store the corresponding values for that particular EmpID using Dictionary and then i will save them to a list corresponding to the EmpID.
Assume that i am having list element as follows
For EmpID 1 i will have 1,2. I will check for the maximum value from the datbase in this list if exists i would like to delete this EmpID from the database.
For EmpID 2 i will have 1,2. But in my database i will have 3 as maximum values. So this one fails . I would like to rollback the previously deleted item .
Is it possible to do with a transaction if so can any one help me in solving this
Sample i code
if(findMax(lst,iEmpID)
{
obj.delete("storeprocname"); // this will occur when my list has maximum value
}
else
{
//Here i would like to rollback my previous one referring to the delete method in class file
}
My sample code
if (findMaxPayPeriodID(lstPayPeriodID, iEmpIDs)) //Assume for the first time maxpayperiod exists and for the second time it fails how to rollback then
{
if (findSequence(lstPayPeriodID)) // Assume this is also true for first time
{
for (int ilstPayperiodID = 0; ilstPayperiodID < lstPayPeriodID1.Count; ilstPayperiodID++)
{
oAdmin.Payperiodnumber = (int)lstPayPeriodID1[ilstPayperiodID];
for (int ilistPayYear = iPayYearcnt; ilistPayYear < lstPayYear1.Count; ilistPayYear++)
{
oAdmin.PayYear = (int)lstPayYear1[ilistPayYear];
iPayYearcnt++;
break;
}
for (int ilistDateTime = idtcnt; ilistDateTime < lstDateTime1.Count; ilistDateTime++)
{
idtcnt++;
oAdmin.PaymentDate = lstDateTime1[ilistDateTime];
break;
}
}
if (oAdmin.deletePayRoll(oSqlTran))
{
oMsg.Message = "Deleted Sucessfully";
oMsg.AlertMessageBox(out m_locallblMessage);
Page.Controls.Add(m_locallblMessage);
oAdmin.FedTaxID = ddlFedTaxID.SelectedValue;
oAdmin.PayFrequency = ddlPaymentType.SelectedValue.ToString();
mlocal_strStoredProcName = "uspSearchPayRoll";
oAdmin.getPayRollDetails(out mlocal_ds, mlocal_strStoredProcName);
//grdPayroll.Visible = true;
grdPayroll.DataSource = mlocal_ds;
grdPayroll.DataBind();
if (mlocal_ds != null)
{
btnDelete.Visible = true;
}
else
btnDelete.Visible = false;
}
lstPayPeriodID.Clear();
lstDateTime.Clear();
lstPayYear.Clear();
iPayIDcnt = 0;
iPayYearcnt = 0;
idtcnt = 0;
}
else
{
rollback should be done
}
You don't provide enough information - esp. since it seems that you will use a Stored Procedure for the delete operation all bets are off...
The only option I can think of is to make sure that you find first the maximum EmpId not from one list BUT from all lists first... then just check that against the DB and act accordingly...
This way the DB will only be hit twice (for the check and for the delete/Stored Procedure)... which is definetely better in terms of scaling etc.

Categories

Resources