How to embed an attribute in a DataRow? - c#

I am doing my project, in which I have a database of books. I have loaded that database in DataTable "Books". There is another DataTable "Watermark_books", which contains all attribute as "Books" datatable has, as well as an extra attribute which is watermark of each row.
I have to calculated watermark, now I have to embed that watermark attribute in "Watermark_books" datatable.
Kindly have a look on code which i have written.
int ky= 0;
double attrib = CalculateWatermarkAttribute(i, j, out ky);
DataRow dataRow = dataSet.Tables["Watermark_Books"].NewRow();
DataRow tmpRow = dataSet.Tables["Books"].Select("id=" + ky)[0];
dataRow.ItemArray = tmpRow.ItemArray; // this copies all columns of one row to new row
dataRow.ItemArray[7] = attrib; // this line of code is not working
dataSet.Tables["Watermark_Books"].Rows.Add(dataRow);
Can anyone point out what is wrong with above mentioned line of code....
Thanks in advance...

Try below code:
int ky= 0;
double attrib = CalculateWatermarkAttribute(i, j, out ky);
DataRow dataRow = dataSet.Tables["Watermark_Books"].NewRow();
DataRow tmpRow = dataSet.Tables["Books"].Select("id=" + ky)[0];
foreach (System.Data.DataColumn column in dataSet.Tables["Watermark_Books"].Columns)
{
if (column.ColumnName == "WatermarkColumn")
dataRow["WatermarkColumn"] = attrib;
else
dataRow[column.ColumnName] = tmpRow[column.ColumnName];
}

Related

datatable get specific column from row

I have the following:
//a datatable with some rows and columns lets say 5x5
var datatable = new DataTable();
var numberofrows = datatable.rows.count;
for (int i = 0; i < numberofrows; i++) {
//for each row, get the 3rd column
var cell = datatable.rows[i].???
}
how do I get the 3rd column for each row?
for 3rd column
var cellValue = datatable.Rows[i][2];
better, if you know the column name,
var cellValue = datatable.Rows[i]["column_name"];
If the table contains 2 columns "Property" and "Value". Contents can be inserted as follows
table.Columns.Add("Property", typeof(string));
table.Columns.Add("Value", typeof(string));
table.Rows.Add("P1", "abc");
table.Rows.Add("P2", "xyz");
To retrive contents of specific column
foreach (DataRow row in table.Rows)
{
if (row["Property"].ToString() == "P1")
{
var value = row["Value"].ToString();
}
}
we can read the particular column values by like this
foreach (DataTable table in ds.Tables)
{
if (table.TableName == "Table1")
{
for (int j = 0; j < table.Rows.Count; j++)
{
int a = Convert.ToInt32( table.Rows[j].ItemArray[3]);
int b = Convert.ToInt32(table.Rows[j].ItemArray[4]);
}
}
}
You can iterate thru the datatable and get every row, which can be thought as an array, so you can pick each element of that particular row using an index (and can also use the name of the column instead of the index, i.e.: row["column3 name"]).
foreach(DataRow row in datatable)
{
Console.WriteLine(row[2]);
}

how to dynamically get a single value from a datatable in C#?

I am new at C#, I have a DataTable named dt; Now I want to get the values from it's each row and a specific column named "Number" from which I can calculate a third column to add. But cant' do it. Any ideas? Please help me.
foreach (DataRow dRow in dt.Rows)
{
int number = dt.Rows[0].Field<int>(1);
dRow[Ratio] = Convert.ToString(((number * 100) / grandTotal)) + " %";
}
Use a loop and the Field method, presuming that Number is an int:
foreach(DataRow row in dt.Rows)
{
int number = row.Field<int>("Number");
// do your calculation
row.SetField("ThirdColumn", someValue);
}

Updating values in DataTable doesn't work

I have code like this:
DataTable dt = new DataTable();
// (...) getting data, displaying on DataGridView - all works fine
int columns = dt.Columns.Count; // getting column count
foreach (DataRow row in dt.Rows)
{
for (int c = 0; c < columns; c++) // c is column index
{
// all old values are positive for debugging
double oldVal = Convert.ToDouble(row.ItemArray[c]);
// new values should become negative
double newVal = oldVal * -1;
row.ItemArray[c] = newVal; // im trying to update value like this
// THIS SHOWS POSITIVE NUMBERS (NOT UPDATED)
this.Text = row.ItemArray[c].ToString(); // this is simple debug
}
}
This is a little more complicated, i simplified code.
Why my values are not updated?
Added later:
One more important thing. This data comes from database view, not table. Of course I want to change that data in my DataTable object, not in database.
In the end do this
dt.AcceptChanges();
This Commits all the changes made to this table since the last time AcceptChanges() was called.
DataTable dt = new DataTable();
// (...) getting data, displaying on DataGridView - all works fine
int columns = dt.Columns.Count; // getting column count
foreach (DataRow row in dt.Rows)
{
foreach (DataColumn c in dt.Columns)
{
// all old values are positive for debugging
double oldVal = Convert.ToDouble(row[c]);
// new values should become negative
double newVal = oldVal * -1;
row[c] = newVal; // im trying to update value like this
// THIS SHOWS POSITIVE NUMBERS (NOT UPDATED)
this.Text = row[c].ToString(); // this is simple debug
}
}
dt.AcceptChanges();
EDIT (Added explaination):
Changes to ItemArray elements are not tracked, so no changes are reflected in the datatable values
However you can use ItemArray to change all the row at once, like this:
dt.Rows[0].ItemArray = new object[] {"new value"};
In this case the changes are tracked, and are reflected in datatable.
Update your foreach loop as
foreach (DataRow row in dt.Rows)
{
for (int c = 0; c < columns; c++) // c is column index
{
double oldVal = Convert.ToDouble(row[c]);
double newVal = -oldVal;
row[c] = newVal;
this.Text = row[c].ToString();
}
}
or you can use foreachinstead of for loop as:
foreach (DataRow row in dt.Rows)
{
foreach (DataColumn c in dt.Columns)
{
double oldVal = Convert.ToDouble(row[c]);
double newVal = -oldVal;
row[c] = newVal;
this.Text = row[c].ToString();
}
}

Copy Data Table to a Data Grid without binding them together

I have two datagrids in my application (dataGridView1 and dataGridView2). I am moving selected items from dataGridView1 into dataGridView2. Here is how I am currently doing this:
DataTable dt = new DataTable("dt");
DataTable id = new DataTable("id");
try
{
if (dataGridView1.Rows.Count > 0)
{
for (int i = 0; i < dataGridView1.Rows.Count - 0; i++)
{
if (dataGridView1.Rows[i].Cells[0].Value != null)
{
DataRow row;
DataRow idRow;
row = dt.NewRow();
idRow = id.NewRow();
idRow["id"] = dataGridView1.Rows[i].Cells[1].Value.ToString();
row["id"] = dataGridView1.Rows[i].Cells[1].Value.ToString();
row["Link Name"] = dataGridView1.Rows[i].Cells[2].Value.ToString();
dt.Rows.Add(row);
id.Rows.Add(idRow);
}
}
dataGridView2.DataSource = dt;
}
However, I also need to be able to remove items from dataGridView2. Currently, the DataTable dt is bound to dataGridView2 and I cant clear it after the items are added because it also clears the dataGridView2.
Basicly, my question would be, is there a way to add the contents of a data table to a data grid without using datagrid.DataSource?
You can manually add each row using the dataGridView2.Rows.Add function. Also, I have typically used the dataGridView2.Row(n).Tag to hold the actual source of that row's data.
int n = dataGridView2.Rows.Add();
DataGridViewRow newRow = dataGridView2.Rows[n];
newRow.Cells[0].Value = "ABC";
newRow.Cells[1].Value = 123;
newRow.Tag = row;

dataSet.GetXml() doesn't return xml for null or blank columns

When I call dataSet.GetXml() I don't get any xml returned for columns with null or blank values. Is there a simple, efficient way to get around this? An example of the problem below. Notice how a2 is missing from the second results section.
<results>
<a1>test1</a1>
<a2>test2</a2>
<a3>test3</a3>
</results>
<results>
<a1>Atest1</a1>
<a3>Atest3</a3>
</results>
The problem is detailed in this Microsoft KB article: http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q317961. See this previous SO question for more detail: DataSet.GetXml not returning null results.
I don't think there is a good solution to your direct question. Given context, there may be another way to approach the problem though.
One solution that worked for me.
First clone the DataTable, make all columns of type string, replace all null values with string.empty, then call GetXml on a new DataSet.
DataTable dtCloned = dt.Clone();
foreach (DataColumn dc in dtCloned.Columns)
dc.DataType = typeof(string);
foreach (DataRow row in dt.Rows)
{
dtCloned.ImportRow(row);
}
foreach (DataRow row in dtCloned.Rows)
{
for (int i = 0; i < dtCloned.Columns.Count; i++)
{
dtCloned.Columns[i].ReadOnly = false;
if (string.IsNullOrEmpty(row[i].ToString()))
row[i] = string.Empty;
}
}
DataSet ds = new DataSet();
ds.Tables.Add(dtCloned);
string xml = ds.GetXml();
I have been searching the whole world for a solution of writing null fields to XML using DataSet.WriteXML(). I found that following works in a performance optimized way. I have created a function for your convenience. Change your dataset tables one after the other by calling the following function and replacing the tables.
private DataTable GetNullFilledDataTableForXML(DataTable dtSource)
{
// Create a target table with same structure as source and fields as strings
// We can change the column datatype as long as there is no data loaded
DataTable dtTarget = dtSource.Clone();
foreach (DataColumn col in dtTarget.Columns)
col.DataType = typeof(string);
// Start importing the source into target by ItemArray copying which
// is found to be reasonably fast for nulk operations. VS 2015 is reporting
// 500-525 milliseconds for loading 100,000 records x 10 columns
// after null conversion in every cell which may be usable in many
// circumstances.
// Machine config: i5 2nd Gen, 8 GB RAM, Windows 7 64bit, VS 2015 Update 1
int colCountInTarget = dtTarget.Columns.Count;
foreach (DataRow sourceRow in dtSource.Rows)
{
// Get a new row loaded with data from source row
DataRow targetRow = dtTarget.NewRow();
targetRow.ItemArray = sourceRow.ItemArray;
// Update DBNull.Values to empty string in the new (target) row
// We can safely assign empty string since the target table columns
// are all of string type
for (int ctr = 0; ctr < colCountInTarget; ctr++)
if (targetRow[ctr] == DBNull.Value)
targetRow[ctr] = String.Empty;
// Now add the null filled row to target datatable
dtTarget.Rows.Add(targetRow);
}
// Return the target datatable
return dtTarget;
}
if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count == 0)
{
foreach (DataTable dt in ds.Tables)
{
foreach (DataColumn dc in dt.Columns)
{
dc.DataType = typeof(String);
}
}
DataRow dr = ds.Tables[0].NewRow();
for (int i = 0; i < dr.ItemArray.Count(); i++)
{
dr[i] = string.Empty;
}
ds.Tables[0].Rows.Add(dr);
}

Categories