Populating one dataset overwrites another dataset result - c#

Its been 2-3 hours and I can't still understand why its happening. Need help.
I am populating dataGridView using dataset. There are two tables master and detail. I am using two datasets to fetch both tables from datasets (Also I've implemented class to fetch from database so I just call that class's function which return dataset containing result and I assign that to my local datasets).
Now what is happening is 1st I fetch detail table and check whether its null etc and if not I fetch second. Here the problem arises as soon second gets populated 1st one overwrites. I am so out of my mind now that I can't understand what is happening. here's my code:
private void txtInvNumber_TextChanged(object sender, EventArgs e)
{
if (txtInvNumber.Text != "")
{
try
{
DataSet dsdetail = new DataSet();
DataTable dtdetail = new DataTable();
string query = "SELECT sell.ItemId 'Item ID',Item 'Item Name' ,sell.Quantity ,Status ,Credit_Limit 'Credit Limit',"
+ "Total_amount 'Total Amount' ,Discount_Allowed 'Discount' ,Discounted_amount 'Discounted Amount' , "
+ "Payable_Amount 'Payable Amount',Advance 'Advance Paid',Amount_Received 'Amount Received', Amount_Receivable 'Amount Receivable' "
+ "FROM dbo.DSelling_Information sell join Item_Infomation it on sell.ItemId=it.Item_ID "
+ "where InvoiceNum = '" + txtInvNumber.Text + "'";
string query_master = "select Sale_Orde_date 'Date', mp.Cust_ID,CUST_Name,Total_Quantity,Total_Amount,"
+ "Amount_Received,Amount_Receivable,Report_Status from dbo.MSelling_Information mp join dbo.Customer_Information cs on mp.Cust_ID=cs.CUST_ID"
+ " where Invoice_num = '" + txtInvNumber.Text + "'";
dsdetail = db.func_ds(query);
if (dsdetail != null && dsdetail.Tables != null && dsdetail.Tables[0].Rows.Count > 0)
{
ds2 = db.func_ds(query_master); <--here dsitem gets populated too.
if (ds2 != null && ds2.Tables != null && ds2.Tables[0].Rows.Count > 0)
{
dtSellDate.Value = DateTime.ParseExact(ds2.Tables[0].Rows[0]["Date"].ToString(), "M/dd/yyyy", CultureInfo.InvariantCulture);
txtCustID.Text = ds2.Tables[0].Rows[0]["Cust_ID"].ToString();
txtCustomerName.Text = ds2.Tables[0].Rows[0]["CUST_Name"].ToString();
txtTotalQuantity.Text = ds2.Tables[0].Rows[0]["Total_Quantity"].ToString();
txtTotalAmount.Text = ds2.Tables[0].Rows[0]["Total_Amount"].ToString();
txtAmountRcvd.Text = ds2.Tables[0].Rows[0]["Amount_Received"].ToString();
txtAmountRcvble.Text = ds2.Tables[0].Rows[0]["Amount_Receivable"].ToString();
txtReportStatus.Text = ds2.Tables[0].Rows[0]["Report_Status"].ToString();
dataGridView1.AutoGenerateColumns = true;
dtdetail = dsdetail.Tables[0];
//dataGridView1.DataSource = db.func_ds(query).Tables[0]; // dataset
dataGridView1.DataSource = dtdetail;
isDgFill = true;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
else
{
ds1.Clear();
dataGridView1.DataSource = null;
dataGridView1.Columns.Clear();
isDgFill = false;
}
}
I tried using new keyword but no luck
dataGridView1.DataSource = new DataTable("dtdetail");
also this:
dataGridView1.DataSource = new DataSet("dsdetail").Tables[0];
Here is another problem:
I tried direct function call on populating data:
dataGridView1.DataSource = db.func_ds(query).Tables[0];
it worked but on cellclick i need to do multiple calculations which includes fetching data from database so whenever i fetch using dataset it just make datasource of datagridview null.
I am using different names for each dataset but nothing is happening. Please if anyone can tell where I am wrong i'll be thankful to him\her a lot.

If you reassigning data source of data grid view It will clear the previous one .I think this the mistake your making.

Related

How to add conditional data from a datatable into another datatable. [error: " no row at position 0] . C#

I am new to programming and got this job to create a tool to convert .DBF table into a .csv file.
so here is the scenario;
The dbf table 'Poles' contain four fields 'pole_id', 'guy_hoa_1', 'guy_hoa_2','guy_hoa_3' and 'guy_hoa_4'.
And the final csv file should show the value in two columns only:'PoleId' and 'HOA' respectively, where PoleID will be == pole_id and HOA= guy_hoa_1 + '|' +guy_hoa_2+'|' +guy_hoa_3 +'|'+ guy_hoa_4.
for example, the Poles table will have data like;
Sample data of Poles table
And, the ouput csv file should show data as follows;
Sample Output CSV file
*The pole_id is the main field and based on it the values of other fields will be selected.
So far I managed to write following code:
enter code here
enter code here
string str = textBox1.Text;
string path = str.Substring(0, str.LastIndexOf("\\") + 1);
string conn = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source = '" + path + "';Extended Properties=dBase IV;User ID=Admin;Password=;";
OleDbConnection connection = new OleDbConnection();
connection.ConnectionString = conn;
connection.Open();
CheckConnectionLabel.Text = "Connected Successfully";
OleDbDataAdapter adapter = new OleDbDataAdapter(#"SELECT pole_id, guy_hoa_1, guy_hoa_2,guy_hoa_3,guy_hoa_4 FROM poles" + ".dbf", connection);
DataSet ds = new DataSet();
DataTable dt = new DataTable();
adapter.Fill(dt);
DataTable dt1 = dt.AsEnumerable()
.Where(r=> r.Field<string>("pole_id")!= null)
.Where(r=> r.Field<string>("pole_id")!=" ")
.CopyToDataTable();
DataTable dtTemp = new DataTable();
dtTemp.Columns.Add("PoleId", typeof(String));
dtTemp.Columns.Add("HOA", typeof(string));
string x = string.Empty;
for (int i=0;i< dt1.Rows.Count;i++)
{
if(dt1.Rows[i]["pole_id"]!= null || dt1.Rows[i]["pole_id"].ToString()!= "")
{
if(dt1.Rows[i]["guy_hoa_1"]!=null && dt1.Rows[i]["guy_hoa_1"].ToString()!="")
{
x =dt1.Rows[i]["guy_hoa_1"].ToString();
}
if(dt1.Rows[i]["guy_hoa_2"]!= null && dt1.Rows[i]["guy_hoa_2"].ToString()!="")
{
x = x + "|" + dt1.Rows[i]["guy_hoa_2"].ToString();
}
if(dt1.Rows[i]["guy_hoa_3"]!=null && dt1.Rows[i]["guy_hoa_3"].ToString()!= "")
{
x = x + "|" + dt1.Rows[i]["guy_hoa_3"].ToString();
}
if(dt1.Rows[i]["guy_hoa_4"]!=null && dt1.Rows[i]["guy_hoa_4"].ToString()!= "")
{
x = x + "|" + dt1.Rows[i]["guy_hoa_4"].ToString();
}
dtTemp.Rows[i]["PoleId"] = dt1.Rows[i]["poles_id"].ToString();
dtTemp.Rows[i]["HOA"] = x ;
}
}
connection.Close();
dataGridView1.DataSource = dtTemp;
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex.Message);
}
}
enter code here
So, through above code I am connected to the dbf table and collected required data in 'dt' table. Then I filtered the data by removing the rows where pole_id was blank/null and put it in another 'dt1' table. Now my purpose was to check the conditions in dt1 table and then fill rows in dtTemp table which would later display the data in datagridview.
The Code is fetching the value of x till last IF statement correctly however nothing is getting filled up in dtTemp datatable and then showing this error.
Please help me and let me know where I am wrong... many thanks in advance!!
I got the solution as follows;
enter code here
object y = dt1.Rows[i]["pole_id"].ToString();
dtTemp.NewRow();
dtTemp.Rows.Add(y ,x);

C#: Deleting row in DataTable does not apply to data bank

My task should be quite simple but after hours and hours I must admit I'm completely stuck!
I simply want to delete a datarow from a datatable. My datatable is a copy of the table in my current dataset in a SQLite databank. It is mandatory to use the table.row.Delete() method. I am aware that delete() just marks the row to be deleted upon table update.
Below is the code I'm currently using:
I retrieve my data via:
public DataTable GetTable(string tableName)
{
string connectionPath = dbVariables.ConnectionString;
try
{
SQLiteConnection myConnection = new SQLiteConnection(connectionPath);
myConnection.Open();
string cmdStr = "SELECT * FROM " + tableName;
DataTable myTable = new DataTable();
SQLiteDataAdapter myAdapter = new SQLiteDataAdapter(cmdStr, myConnection);
myAdapter.FillSchema(myTable, SchemaType.Source);
myTable.Columns[dbVariables.ClassesID].AutoIncrement = true;
myTable.Columns[dbVariables.ClassesID].AutoIncrementSeed = 1;
myTable.Columns[dbVariables.ClassesID].AutoIncrementStep = 1;
myAdapter.Fill(myTable);
myConnection.Close();
return myTable;
}
catch (SQLiteException e)
{
MessageBox.Show(e.ToString());
return null;
}
}
Here I manipulate my data:
if (myResult == DialogResult.Yes)
{
//killTable.AcceptChanges();
DataRow[] dr = killTable.Select("" + cmVariables.ClassName + " = '" + cmbClasses.Text + "'");
//First I need to evaluate the row index of the row I want to delete
string indexName = (killTable.Rows.IndexOf(dr[0])).ToString();
int i = Int32.Parse(indexName);
// And we are done - I got my row index
DataRow modifiedRow = killTable.Rows[i];
killTable.Rows[i].Delete();
//I inserted this messagebox just to see the rowstatus - and yes, it is marked as deleted on runtime...
MessageBox.Show(killTable.Rows[i].RowState);
// I refer to this in the text below
killTable.AcceptChanges();
killClass_Execution(killTable, cmbClasses.Text, ShortClassNm);
}
And at least the code to update my datatable back to the databank:
public void UpdateTable(string tableName, DataTable sourceTable, bool newOrEdit)
{
try
{
string connectionPath = dbVariables.ConnectionString;
//Connection erstellen --> der connectString gibt dabei den Pfad an.
SQLiteConnection myConnection = new SQLiteConnection(connectionPath);
myConnection.Open();
//Einen Befehls-String erstellen, der das UPDATE-Command auslöst
// UPDATE cm_ClassTest SET className = userEditInput WHERE className = 'oldClassName'
string myUpdateString = "SELECT * FROM " + tableName + "";
SQLiteDataAdapter myAdapter = new SQLiteDataAdapter(myUpdateString, myConnection);
SQLiteCommandBuilder comBuild = new SQLiteCommandBuilder(myAdapter);
myAdapter.DeleteCommand = comBuild.GetDeleteCommand(true);
myAdapter.UpdateCommand = comBuild.GetUpdateCommand(true);
myAdapter.InsertCommand = comBuild.GetInsertCommand(true);
myAdapter.Update(sourceTable);
myConnection.Close();
if (newOrEdit == true)
{
MessageBox.Show("Klasse erstellt!");
}
else
{
MessageBox.Show("Klasse aktualisiert!");
}
}
catch (SQLiteException e)
{
MessageBox.Show(e.ToString());
}
}
In the code block for manipulating data you will find the AcceptChanges() method. At this time, there may have been no other changes appeared to my datatable - so after app start, deleting a row may be the users first action.
Also: each entry in my dataset is unique (school classes that are labeled with a unique class name).
Any help will be highly appreciated!
Regards,
Aran
OK - so I succeeded (finally). Debugging showed no issues, except for AcceptChanges() which got a call but did not result in actually deleting the dataRow.
All I can think of right now is that my primary approach to it was part of the problem: I get my DataTable right from the DataBase, do all the manipulations with it, and then send it back to DB via Update (see my update method above). The SQLite CommandBuilder seems not capable of interpreting my DAtaRow which is by then flagged 'Deleted', but kind of rubber-stamps it to the end of the method without throwing an exception.
By doing so I tried the GetChanges-Method:
DataRow[] dr = killTable.Select("" + cmVariables.ClassName + " = '" + cmbClasses.Text + "'");
string indexName = (killTable.Rows.IndexOf(dr[0])).ToString();
int i = Int32.Parse(indexName);
killTable.Rows[i].Delete();
DataTable killItTable = killTable.GetChanges(DataRowState.Deleted);
killClass_Execution(killItTable, cmbClasses.Text, ShortClassNm);
Now it's working - the copy of killTable (killItTable - stupid I know, but first thing I do tomorrow morning is give it better names :) ) provides info for the sql commandbuilder which seems to be recognized by it.
Whatever it is - it now works.
I think this is not supposed to happen - if someone can come up with any good suggestions, on how to improve my approach, I shall be glad.
best regards

Pulling a SELECT query into a datatable and accessing it

I'm writing a small ASP.net C# web page and it keeps giving me an error stating:
There is no row at position 0.
I'm probably doing it wrong but here is some of my code:
string SqlQuery = "SELECT * ";
SqlQuery += " FROM main_list";
SqlQuery += " WHERE ID = #FindID";
SqlConnection conn = new SqlConnection("server=???;database=contacts;User
ID=???;Password=???;");
conn.Open();
SqlCommand SqlCmd = new SqlCommand(SqlQuery, conn);
SqlCmd.Parameters.Add("#FindID",searchID);
SqlDataAdapter da = new SqlDataAdapter(SqlCmd);
try {
da.Fill(dt);
fillData(p);
}
catch {
txtId.Text = "ERROR";
}
And FillData is the following:
protected void fillData(int pos) {
txtId.Text = dt.Rows[pos]["ID"].ToString();
txtCompany.Text = dt.Rows[pos]["Company"].ToString();
txtFirstName.Text = dt.Rows[pos]["First_Name"].ToString();
txtLastName.Text = dt.Rows[pos]["Last_Name"].ToString();
txtAddress1.Text = dt.Rows[pos]["Address1"].ToString();
txtAddress2.Text = dt.Rows[pos]["Address2"].ToString();
txtCity.Text = dt.Rows[pos]["City"].ToString();
txtState.Text = dt.Rows[pos]["State"].ToString();
txtZipCode.Text = dt.Rows[pos]["ZipCode"].ToString();
txtPhoneNum1.Text = dt.Rows[pos]["Phone_Num"].ToString();
txtPhoneNum2.Text = dt.Rows[pos]["Phone_Num2"].ToString();
txtFax.Text = dt.Rows[pos]["Fax_Num"].ToString();
txtEmail.Text = dt.Rows[pos]["Email"].ToString();
txtNotes.Text = dt.Rows[pos]["Notes"].ToString();
txtCategory.Text = dt.Rows[pos]["Category"].ToString();
txtSubCategory.Text = dt.Rows[pos]["SubCategory"].ToString();
txtDateAdded.Text = dt.Rows[pos]["DateAdded"].ToString();
txtDateModified.Text = dt.Rows[0]["DateModified"].ToString();
}
Here is the call that errors out:
protected void btnPrev_Click(object sender, EventArgs e) {
p--;
lblPage.Text = p.ToString();
fillData(p-1);
}
protected void btnNext_Click(object sender, EventArgs e) {
p++;
lblPage.Text = p.ToString();
fillData(p-1);
}
I'm trying to cycle thru the Rows[0] to Rows[1] or however many there is but it gives me the error about no row at position 0 or position 1. It only fills once and then errors out.
EDIT:
I'm trying to access the second row returned by the database after already accessing one row already. For example: Rows[0] is accessible fine but then when I try to read Rows[1] it errors and says it doesn't have a row in position 1. I can revise the code to return Rows[1] and it works but when I try to access Rows[0] it breaks. This is why I pass the variable (p) to fillData so it can show only that Rows value. Thanks!
EDIT 2: I believe it's because there is a postback that wipes the values retrieved by the database. Is there a way to get the database entries to stay even after a postback? If not I am guessing I will have to query the database every time.
The error message indicates there are no rows being returned by SQL. Are you sure there is data to be returned.
When you use dt.Rows[0] you are effectively saying "take the first row that comes back, and get a value from it." If the DataTable doesn't have any rows (i.e. your SQL query returns no matches), that's like saying "Here is a plate that contains no apples. Take the first apple and tell me what colour it is" - see? Doesn't make sense.
What you should do is check whether there are any rows before you try to read them...
if(dt.Rows.Count > 0)
{
// do stuff here.
}
Use Linq and a stored procedure it is much nicer
datacontext context = new datacontext();
var result = context.MyStoredProc(searchID).FirstOrDefault();
Try changing
SqlCmd.Parameters.Add("#FindID",searchID);
to
SqlCmd.Parameters.AddWithValue("#FindID",searchID);
Check your query on your database, make sure rows are actually being returned. Also, it's bad practice to put your query directly into your code like that, especially when using parameters. You might want to try something like this:
private Int32 CallStoredProcedure(Int32 FindId)
{
using (var dt = new DataTable())
{
using (var conn = new SqlConnection(ConnectionString))
{
using (var sqlCmd = new SqlCommand("SEL_StoredProcedure", conn))
{
using (var sda = new SqlDataAdapter(sqlCmd))
{
sqlCmd.CommandType = System.Data.CommandType.StoredProcedure;
sqlCmd.Parameters.AddWithValue("#FindId", FindId);
sqlCmd.Connection.Open();
sda.Fill(dt);
}
}
}
if (dt.Rows.Count == 1)
return Convert.ToInt32(dt.Rows[0]["ID"]);
else if (dt.Rows.Count > 1)
throw new Exception("Multiple records were found with supplied ID; ID = " + studentId.ToString());
}
return 0;
}
To set up your stored procedure, on your database run this:
CREATE procedure [dbo].[SEL_StoredProcedure]
#FindId int = null
as
SELECT * FROM main_list where ID = #FindId
Just remove the index identifier from the code:
e.g.
txtId.Text = dt.Rows["ID"].ToString();

NullReferenceException error when searching database table for entries

I'm working on a relatively straight forward C# project that connects an Access Database via OleDb with various functions such as adding, deleting and editing records. Now, everything has worked fine up until trying to implement a database search.
The following line (in the searchbox code) throws up the exception during debug, but I am unsure what is actually a null value that is causing it to break.
ReturnedResults = DBDataSet.Tables["Movies"].Select("Title like '%" + Search + "%'");
So the goal is to search through the 'Movies' table in the database and find movies based on the user's input (stored in the 'Search' string).
The search box's code can be found below, and the database initialisation and connection is provided at the bottom.
private void SearchTextBox_Changed(object sender, EventArgs e)
{
string SearchString = SearchTextBox.Text.ToString();
int Results = 0;
DataRow[] ReturnedResults;
ReturnedResults = DataSet.Tables["Movies"].Select("Title like '%" + SearchString + "%'");
Results = ReturnedResults.Length;
if (Results > 0)
{
SearchResultsBox.Items.Clear();
for (int i = 0; i <= Results; i++)
{
DataRow Row;
Row = ReturnedResults[i];
SearchResultsBox.Items.Add(Row["Title"].ToString());
}
}
else
{
SearchResultsBox.Items.Clear();
MessageBox.Show("Error! No items found.");
}
}
For some context here is the main database initialisation/connection and the form load events:
public partial class BaseForm : Form
{
System.Data.OleDb.OleDbConnection Connection;
DataSet DataSet;
System.Data.OleDb.OleDbDataAdapter DataAdapter;
int MaxRows = 0;
int CurrentRow = 0;
public BaseForm()
{
InitializeComponent();
}
private void BaseForm_Load(object sender, EventArgs e)
{
Connection = new System.Data.OleDb.OleDbConnection();
Connection.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;DataSource=Movies.accdb";
Connection.Open();
DataSet = new DataSet();
string sq1 = "SELECT * From Movies";
DataAdapter = new System.Data.OleDb.OleDbDataAdapter(sq1, DBConnection);
DataAdapter.Fill(DBDataSet);
MaxRows = DataSet.Tables[0].Rows.Count;
DisplayRecord();
}
Multiple things can be null in your statement. DBDataSet can be null, or the table Movies doesn't exits. You may add following check before the line.
if(DBDataSet != null &&
DBDataSet.Tables.Count > 0 &&
DBDataSet.Tables["Movies"] != null)
{
ReturnedResults = DBDataSet.Tables["Movies"].Select("Title like '%" + Search + "%'");
//.... rest of your code
You may also try accessing the record against Tables[0] instead of Table Movies
EDIT:
For your next problem, mentioned in the comment, your for loop is executing till the length. It should be like:
for (int i = 0; i < Results; i++) // Less than (<) not less than equal to
{
DataRow Row;
Row = ReturnedResults[i];
SearchResultsBox.Items.Add(Row["Title"].ToString());
}
You need to modify the condition and remember the index starts from 0 and you will get rows till Result - 1
In your case multiple null reference is occur in your code as per your comment you got error in following line
ReturnedResults = DBDataSet.Tables["Movies"].Select("Title like '%" + Search + "%'");
In above DBDataSet may be null or its table (Movies) has no row etc.. so better way t check before filter
if(DBDataSet != null &&
DBDataSet.Tables.Count > 0 &&
DBDataSet.Tables["Movies"] != null && DBDataset.Tables["Movies"].Rows.Count > 0)
{
ReturnedResults = DBDataSet.Tables["Movies"].Select("Title like '%" + Search + "%'");
}

Why am I getting a NullReferenceException on a DataSet?

I'm opening up a database query from the Northwind database for each item that my ShoppingCart entails. It is to take ProductID and UnitsInStock out from the Products table. After I take the two columns out from the database to save the data into a DataTabel ds. Then I compare to make sure the quantity user entered is less than the column units in stock in the database.
theCart.Values is part of ICollections.
I am gettign error: from my exception message: "There was a problem connecting to the database: Object reference not set to an instance of an object."
Here's the code.
DataSet ds = new DataSet();
OleDbConnection conn = new OleDbConnection((string)Application["DBConnectionString"]);
foreach (OrderItem item in theCart.Values)
{
string selectionString =
"SELECT Products.ProductID, Products.UnitsInStock " +
"FROM Products" +
"WHERE Products.ProductID = " + item.ProductID + ";";
try
{
OleDbCommand cm = new OleDbCommand(selectionString, conn);
OleDbDataAdapter da = new OleDbDataAdapter();
da.SelectCommand = cm;
da.Fill(ds);
da.Dispose();
if (ds.Tables["Products"].Columns.Count != 0 &&
ds.Tables["Products"].Rows.Count != 0)
{
for (int index = 0; index < ds.Tables["Products"].Rows.Count; index++)
{
if (item.ProductID == int.Parse(ds.Tables["Products"].Rows[index][indexOfProductID].ToString()))
{
if (item.QuantityOrdered > int.Parse(ds.Tables["Products"].Rows[index][indexOfUnitsInStock].ToString()))
{
hasStock = false;
int inStock = int.Parse(ds.Tables["Products"].Rows[index][indexOfUnitsInStock].ToString());
txtUnderstockedItems.Text += "Sorry we do not have enough stock of item: " + item.ProductName +
"<br> Currently, " + item.ProductName + " (ID:" + item.ProductID + ") has " + inStock + " in stock.";
}
else
{//can output how many items in stock here.
hasStock = true;
}
}
}
}
catch (Exception ex)
{
txtUnderstockedItems.Text = "There was a problem connecting to the database: " + ex.Message;
}
finally
{
conn.Close();
}
}
}
Rows or Columns is most likely null. Inspect ds prior to that if statement. A common reason something like this would happen is that the Products table returned nothing. You can't get the property of an object that does not exist, thus the exception. You should do a != null comparison instead of checking the count. If the length is zero the code inside the loop will never execute but you won't crash or anything.
if (ds.Tables["Products"].Columns != null && ds.Tables["Products"].Rows != null)
Just a heads up, this will cause no problems if your row count is zero, but you may need some logic within the loop to check that the columns you're planning to access exist.
You are trying to get the table from the dataset with its hardcoded name as to what you see in the database, I just ran a test on a similar pattern and it looks like when you create a Dataset and fill it from the database as you are doing, the table name is not copied from the Database. As Tim suggested, you should check for ds.Table[0]
DataTableCollection.Item returns null if there's no table with the specified table-name.
If a command does not return any rows, no tables are added to the DataSet, and no exception is raised. So i assume that there's no table in the DataSet because no rows are returned.
I would initialize a single DatatTable manually instead and use the overload of Fill which takes a DataTable.
Dim table = new DataTable("Products")
da.Fill(table)

Categories