Assignment and Binding - c#

I have a problem.Let's explain this:
I create a DataTable 'DataT' variable and added row to this variable.SameTime i have datagridview. After i assingmented 'DataT' to DataSource property of DataGridView.
I get 'DataT' Rows.Count property.It's value 10.But this value decrease from 10 to 5 when i removed 5 Rows of DataGridView.
So why decrease my value i just remove Rows of DataGridView but i did not remove rows of 'DataT' although rows count of 'DataT' decrease from 10 to 5.
I have not solve this problem.
EDIT:
Yes i bound datatable.But same problem there is other state.I explain with a example:
DataTable Table1 = new DataTable();
DataTable Table2 = new DataTable();
DataRow Rows;
private void Form1_Load(.......)
{
Tablo1.Columns.Add("Column1");
Tablo1.Columns.Add("Column2");
Rows = Table1.NewRow();
Rows[0] = "Hello";
Rows[1] = "Word";
Table1.Rows.Add(Rows);
Rows = Table1.NewRow();
Rows[0] = "Hello";
Rows[1] = "Word";
Table1.Rows.Add(Rows);
Table2 = Table1;
datagridview1.DataSource = Table1;
//This datagridview1 has 2 Rows and Table1 has 2 Rows.
datagridview1.Rows.RemoveAt(0);
//I am Removing one Row of datagridview1.Not from Table1.
//But Automatic removing Rows from Table1.
//Result=datagridview1 has 1 Row and Table1 has 1 Row.Why do remove rows from Table1?
//Even Rows Remove from Table2 when i remove rows from datagridview1.
}

As Henk Holterman pointed out in comment there are two reasons making Table2 to change
since Table1 is used as DataSource for grid any changes in the grid will be reflected in it. This is expected behavior of GridView.
GridView has its own Rows collection that is updated when one sets DataSource. Any changes to Rows collection (like removing item) are applied to DataTable set as data source. As result datagridview1.Rows.RemoveAt(0); actually indirectly removes row from the object referenced by Table1.
Both of your variables (Table1 and Table2) point to the same object - so whenever anything happens to the DataTable (i.e. row removed by GridView) the change is visible when you check either of variables.
Following code performs "shallow copy" when you seem to expect complete clone similar to behavior of int:
Table2 = Table1;
After that assignment both Table1 and Table2 refer to DataTable created on DataTable Table1 = new DataTable(); line.
See more What is the difference between a deep copy and a shallow copy?

Related

Insert a row from one DataTable in the middle of another DataTable

So, I have two DataTables. I can easly ADD rows from one to another with this:
table1.Rows.Add(table2.Rows[0].ItemArray);
But I want to insert the row in particular place, not on the bottom of the table1. Tried to use the table1.Rows.InsertAt, but the problem with it is that you need the DataRow class (which I can't figure out how to get), and also you can't do table.Rows.InsertAt(table1.Rows[0], idex); because it says that the row belongs to another table.
(table2 is source, table1 - target)
You can clone the source row's items and then create a DataRow using them:
var sourceItems = (object[])(table2.Rows[0].ItemArray.Clone());
DataRow targetRow = table1.NewRow();
targetRow.ItemArray = sourceItems;
table1.Rows.InsertAt(targetRow, index);
(note that it's not clear in your question which datatable is the source and which is the target, I assumed table2 is the source and table1 the target)

Compare datatable and return rows with changes

I am trying to compare two datatable and return only rows which has changes. In the below code I am cloning dt2 into dt3 but it doesn't pick the rows with changes instead it puts everything in there. Pls suggest some options.
Even if a single cell value is modified then I need to pick that row. Both datatable with have same set of rows and column each time I compare.
Table 1 Table 2
ID Name ID Name
1 Mark 1 Mark
2 Spencer 2 Spencer
3 Ryan 3 George
Table 3 Expected Result:
ID Name
3 George
CODE:
DataTable dt3 = new DataTable();
// It will compare the 2nd table with the 1st table
var contacts = dt2.AsEnumerable().Except(dt1.AsEnumerable(), DataRowComparer.Default);
dt3 = dt2.Clone();
foreach (DataRow rows in contacts)
{
dt3.ImportRow(rows);
}
You do not need two tables for this purpose. Simply calling GetChanges() on the second DataTable will get you the last row that has changed. Make sure you haven't (directly or indirectly) called AcceptChanges() on the DataTable, otherwise GetChanges() won't return anything.
DataRow exposes a property named RowState that is set to Modified when one or more columns of it get changed. AcceptChanges() and RejectChanges() reset this flag back to Unmodified.
You can even get the original value (Ryan in your case) and current value (George in your case) of a column by calling the indexer of DataRow with the second parameter (RowVersion) set to Original and Current respectively.
Try this:
dt1.Select()
.Join(dt2.Select(), x => x["Id"], y => y["Id"], (x, y) => new { x, y })
.Where(z => z.x["Name"] != z.y["Name"])
.Select(z => z.y);
Here dt1 is Table 1 and dt2 is Table 2.
It tries to join tables by Id, and then filters out records with same Name.

how to get specific column value after filling dataset with tableadapter

for example:
table1 has two columns "col1" and "col2"
this.table1TableAdapter.FillByParam(appDataSet.table1,param);
this returns 1 row
how to set col1 and col2 values to variable?
It would be great if someone post example with code.
Thanks.
This line fills a given DataTable from the query that is specififed as SelectCommand in the TableAdapter. So you say that it just contains a single record?
You can use FirstOrDefault to get that DataRow. Since it's a strongly typed DataTable you have an autogenerated DataTable and DataRow with typed properties and names that are the same as the ctypes and names in database.
So assuming you have two Label controls which Text properties you want to set from the two properties in the row:
appDataSet.table1Row row = appDataSet.table1.FirstOrDefault();
if(row != null)
{
Label1.Text = row.col1;
Label2.Text = row.col2;
}

making rows distinct and showing all the columns

In my project there are two datatables dtFail and dtFailed (dtFailed has nothing but column names declarations). dtFail has duplicate "EmployeeName" column values. so i took a dataview dvFail and did the process to make them distinct as shown in the below code:
dtFail
I tried the below code:
DataView dvFail = new DataView(dtFail);
dtFail = dvFail.ToTable(true, "EmployeeName"); //showing only one column in dtFail
dtFailed (only one column)
If i do like below
DataView dvFail = new DataView(dtFail);
dtFail = dvFail.ToTable(true, "EmployeeName","EmployeeRole","Status");
dtFailed (showing but with duplicate rows)
Then the datatable dtFailed is storing duplicate "EmployeeName" also.
Please Help
Thanks in Advance.
Try this query-
DataTable distinctTable = originalTable.DefaultView.ToTable( /*distinct*/ true);
For more info hit below link-
https://social.msdn.microsoft.com/Forums/en-US/ed9c6a6a-a93e-4bf5-a892-d8471b84aa3b/distinct-in-datatable-or-dataview?forum=adodotnetdataset
I hope this would have helped you.
SOLUTION 1:
Based on the question my understanding is, we need to consider duplicates based on EmployeeName and we need not worry about other columns. If that is the case below solution works better.
foreach(DataRow r in dtFail.AsEnumerable())
{
if (!dt1.AsEnumerable().Any(r1 => r1["EmployeeName"] == r["EmployeeName"]))
{
// if you don't want to copy entire row create new DataRow
// with required fields and add that row.
dt1.Rows.Add(r.ItemArray);
}
}
if you want you can put dt1 back to dtFail.
SOLUTION 2:
If we need to consider distinct rows I prefer below solution.
var temp = dtFail.AsEnumerable().Distinct();
dtFail = temp.CopyToDataTable();
I'm not sure it will be helpful or not. As far as I get from your question that you want EmployeeName to be distinct irrelevant to other columns. But if you do ToTable and turn on the distinct flag it will give all the distinct rows, doesn't matter how many columns are involved there. So if you mention only EmployeeName it will obviously give you distinct EmployeeNames, not all the columns associated with it.
So, thats what I did, initially select only the distinct EmployeeName columns and put it into a temp DataTable dtt.
DataTable dtt = dvFail.DefaultView.ToTable(true, "EmployeeName");
Secondly I've created another temp DataTable where we put the segregated rows from the main DataTable dtFail and set the column names manually.
DataTable TempDataTable = new DataTable();
DataTable dtFailed = new DataTable();
Prepare the columns in the dtFailed DataTable.
if (dtFailed.Columns.Count == 0)
{
dtFailed.Columns.Add("EmployeeName");
dtFailed.Columns.Add("EmployeeRole");
dtFailed.Columns.Add("Status");
dtFailed.Columns.Add("Date");
}
Loop through the distinct EmployeeName dtt DataTable and match the EmployeeName and keep that selected first row in the TempDataTable. Finally all rows transferred into the dtFailed.
for (int j = 0; j < dtt.Rows.Count; j++)
{
string EmployeeName = dtt.Rows[j]["EmployeeName"].ToString();
TempDataTable = dvFail.Select("EmployeeName = " + EmployeeName).CopyToDataTable();
dtFailed.Rows.Add(TempDataTable.Rows[0].ItemArray);
}

Assign a DataTable to a DataTable

I want to assign a DataTable (dataTable1) to another DataTable (dataTable2) and remove some columns in the latter DataTable. For example I have the following code:
DataTable dataTable2 = dataTable1;
dataTable2.Columns.Remove("column1");
dataTable2.Columns.Remove("column2");
It turns out both DataTable (dataTable1 and dataTable2) have the columns removed. I do not understand why dataTable1 would have column1 and column2 removed as well, while I am only removing columns in dataTable2.
[EDITED - with answer]
Should use Clone() AND ImportRow() instead of a pointer assignment.
DataTable dataTable2 = dataTable1.Clone()
for (int i = 0; i < dataTable1.Rows.Count; i++)
{
dataTable2.ImportRow(dataTable1.Rows[i]);
}
This happens because dataTable2 points to the same table as dataTable1. To resolve this problem, use the DataTable's Clone method to create a new DataTable with the same structure:
DataTable dataTable2 = dataTable1.Clone();
dataTable2.Columns.Remove("column1");
dataTable2.Columns.Remove("column2");
datatable is reference type so thats why both of the tables are changing if changes are made in one. and instead of looping through data rows you could either call dataTable1.Copy() to copy data and schema to another datatable.
datatable.clone() is pass by reference. u have to give it by value.
DataTable dataTable2=dataTable1.Copy();
dataTable2.Columns.Remove("column1");
dataTable2.Columns.Remove("column2");
Now removing From datatable2 does not effect DataTable1

Categories

Resources