C#: How do I iterate the contents in a DataColumn? - c#

I have a database column I simply need to check to see if a value is there.
DataTable dt = masterDataSet.Tables["Settings"];
DataColumn SETTINGS = dt.Columns["DEFAULTSETTINGS"];
I just need to iterate over the values in this column to see if a value exists.
Help

You iterate the rows, not the column
DataColumn SETTINGS = dt.Columns["DEFAULTSETTINGS"];
foreach(DataRow row in dt.Select())
{
object columnValue = row[SETTINGS];
// Do something with columnValue
}

There's no need to use Linq or iterate manually through your DataRows as plain old ADO.NET has a couple of solutions such as DataTable.Select and DataView.RowFilter.
string value = "default";
bool found = dt.Select("DEFAULTSETTINGS = " + value).Length > 0;
It's obvious that once you get the filtered rows, you can do whatever you want with them. In my example, I just checked to see if any row was within the criteria but you can manipulate them how you see fit.

You can use linq in .net 3.5:
DataColumn col = dt.Columns["DEFAULTSETTINGS"];
object value = //expected value
bool valueExists = dt.AsEnumerable().Any(row => row.Field<object>(col).Equals(value));
EDIT: It seems from the comments you're trying to see if the 'DEFAULTSETTINGS' column contains the string 'default'. The Field extension method simply casts the object in the datarow at that column into the given type, so you can change the type parameter rather than use ToString(). So for your example you can probably use this:
DataColumn col = dt.Columns["DEFAULTSETTINGS"];
bool valueExists = dt.AsEnumerable().Any(row => "default".Equals(row.Field<string>(col), StringComparison.OrdinalIgnoreCase);

Related

How can I get value of a specific cell in DataTable in c#?

I am new to c# and using windows forms.
I have a dataTable as shown in screenshot, I want to get a value of specific cell in button_Text column based on Button_Name column value and save it in a string. I know I can use this code :
string s = DataTable.Rows[2][1];
But I do not want to use it because I do not want to use numbers between brackets to index the cell value but instead I want to use the a Button_Name column value and button_Text column name to index the cell value.
For example:
string s = DataTable.Rows[ButtonUC1_3][Button_Text]; // but it gives error : "Argument1: can not convert from string to int"
I hope it is clear enough. Anyone knows how to achieve this? Thank you
Use LINQ to DataSet there you can use column names
string value = dataTable.AsEnumerable()
.Where((row) => row.Field<string>("button_Name").Equals("ButtonUC_1"))
.Select((row) => row.Field<string>("button_Text"))
.FirstOrDefault();
Here Rows Must be Int formet,But Columns string allowed,
below one is error
string s = DataTable.Rows["ButtonUC1_3"]["Button_Text"];
the correct formet is,
string s = DataTable.Rows[2]["Button_Text"];
It will give the cell value,.
DataTable Rows don't have names, they're indexed only by number. If you want to access the rows through the names you specified, you need to use your own mapping, e.g. var rowMapping = new Dictionary<string,int>() { { ButtonUC1_3, 0}, ... } and then access the DataTable like this DataTable.Rows[rowMapping[ButtonUC1_3]][Button_Text].
Obviously, this is not the only way how to do it, you could define an enum, integer constants, etc. It all depends how many rows you have and how you use your DataTable.

c# adding row that already belongs to a datatable

I have a datatable DTgraph, that datatable has a column named Campaign. that column could have one of three unique values, which are IVR, City, City2`. So the rows are like this:
I have a datatable has data like this format
........ IVR........
.........IVR........
**.........IVR........**
.........City1......
.........City1......
**.........City1......**
.........City2......
.........City2......
**.........City2......**
I want to take the last row of each unique value for that column, In other words, I want to take the rows that are bold. I did almost everything like this:
var cRows = new Dictionary<string, DataRow>(StringComparer.InvariantCultureIgnoreCase);
foreach (DataRow oRow in DTgraph.Rows)
{
var sKey = oRow["Campaign"].ToString();
if (!cRows.ContainsKey(sKey))
{
cRows.Add(sKey, oRow);
}
else
{
cRows[sKey] = oRow;
}
}
var oNewTable = DTgraph.Clone();
foreach (var oRow in cRows.Values)
{
oNewTable.Rows.Add(oRow);
}
As you see, I put the data in dictionary and transferred the dictionary to a datatable at the end.
My problem is that on this line:
cRows.Add(sKey, oRow);
I get an error:
The row is already belongs to another datatable
Note: I need to solve that exception, I don't need a new way of doing my goal
Note: I was wrong, the exception is on this line
oNewTable.Rows.Add(oRow);
To be honest I don't 100% understand your question, however to fix the exception:
The row is already belongs to another datatable.
Change:
oNewTable.Rows.Add(oRow);
To:
oNewTable.ImportRow(oRow);
Alternatively create a new row and clone the ItemArray.
foreach (var oRow in cRows.Values)
{
var newRow = oNewTable.NewRow();
newRow.ItemArray = oRow.ItemArray.Clone() as object[];
oNewTable.Rows.Add(newRow);
}
Use NewRow() function of the new table and then use oRow.ItemArray property to get values from the source row and copy them the newly created row's ItemArray. An example would be:
Array.Copy(oRow.ItemArray, oNewTable.NewRow().ItemArray, oRow.ItemArray.Length)
However, remember that this would not preserve original values and current state from the source row (which I don't think you're using here anyway). If those things matter, go for ImportRow() solution which preserves source row's state when copying.

Adding values to a Row ItemArray

I am using some DataRow and with it, some ItemArray.
I know how to get the value into a ItemArray, but I don't know how to set values, when I create a new Row.
So I tried this :
DataRow newRow = vDsMod.Tables[0].NewRow();
newRow.ItemArray[0] = "".ToArray();
newRow.ItemArray[1] = "".ToArray();
newRow.ItemArray[2] = "Employee".ToArray();
newRow.ItemArray[3] = "".ToArray();
vDsMod.Tables[0].Rows.Add(newRow);
Or
DataRow newRow = vDsMod.Tables[0].NewRow();
newRow.ItemArray.SetValue("", 0);
newRow.ItemArray.SetValue("", 1);
newRow.ItemArray.SetValue("Employee", 2);
newRow.ItemArray.SetValue("", 3);
vDsMod.Tables[0].Rows.Add(newRow);
But I only got empty fields in the ItemArray.
The value 0,1,3 can be empty, and as the ItemArray of the other lines has a lenght of 4, I also set 4 values.
How can I do what I want?
ItemArray returns an object[] which includes all fields. By accessing it via index here:
newRow.ItemArray[0] = "".ToArray();
you are accessing a single field and asigning a new value. But you're assigning a char[] because you use String.ToArray(), that is pointless.
Instead i would use the strongly typed SetField method which also support nullable types:
DataRow newRow = vDsMod.Tables[0].Rows.Add();
newRow.SetField(0, "");
newRow.SetField(1, "");
newRow.SetField(2, "Employee");
newRow.SetField(3, "");
With Rows.Add(); the DataRow is already added. It's a matter of taste whether to use DataTable.NewRow() and add it later manually or DataTable.Rows.Add().
You can go as below ..
DataRow relation;
// Declare the array variable.
object [] rowArray = new object[2];
for(int i = 0; i <10; i++)
{
rowArray[0]=null;
rowArray[1]= "item " + i;
relation = dt.NewRow();
relation.ItemArray = rowArray;
dt.Rows.Add(relation);
}
I hope it will help you
Yeah it is on microsoft help. But according to your question you seems you didn't search a litle bit you just pposted the question. You want to know just how to initialize the ItemArray (As much i could understand) and you can find a lot of examples related to this.

sorting and updating datatable not producing expected results

EDIT: Solved this myself - obviously won't work as sorting the dataTable doesn't sort the underlying data - created a dataView from the table, works fine.
I have a datatable which I am sorting and then iterating through to remove duplicate values in one column, however the output is not as expected.
Datatable structure:
infoRow["Title"]
infoRow["QuickLink"]
infoRow["Description"]
infoRow["Date"]
infoRow["MonthName"]
I'm sorting like this, which works fine, and produces a table ordered in ascending month order:
dataTable = dataTable.DefaultView.ToTable(true);
dataTable.DefaultView.Sort = "Date asc";
After the sort, I'm using the code below to compare each row to the previous, and if the MonthName value is the same, replaced it with an empty string:
string prevMonthName = "";
foreach (DataRow row in dtEvents.Rows)
{
string strMonthName = row["MonthName"].ToString();
if (strMonthName == prevMonthName)
{
row["MonthName"] = "";
row.AcceptChanges();
}
prevMonthName = strMonthName;
}
So, the problem I'm having is that even when I run the MonthName loop after the sort, it appears to be running against the unsorted data. It's like DefaultView.Sort only affects the rendered output without physically reordering the table, hence the second part of the code doesn't produce the result I need. Should I maybe be using DataView or am I just way off track...
I was actually having a similar, but slightly different problem and your question gave me an idea. As it turns out, your code was incredibly close to what you (and I) need. All you need to do is flip those two lines of sorting code like so:
dataTable.DefaultView.Sort = "Date ASC";
dataTable = dataTable.DefaultView.ToTable(true);
Now, the first line of code sorts the DefaultView. This would be enough for your DataGridView or ComboBox or whatever you're using for display, because they make use of the DefaultView. However, the DataTable, itself, remains unsorted. Therefore, the second line sets the DataTable to look exactly like the sorted DefaultView.
I just noticed your edit at the top which says you've solved it. That 'solution' seems to be more of a workaround. Seeing as how you had the right code but in the wrong order, I figured you would be interested in this answer.
Assuming that dtEvents is referencing the same object as datatable, you could try this:
string prevMonthName = "";
foreach (DataRowView row in dtEvents.DefaultView)
{
string strMonthName = row["MonthName"].ToString();
if (strMonthName == prevMonthName)
{
row["MonthName"] = "";
row.AcceptChanges();
}
prevMonthName = strMonthName;
}
Just for fun I figured out how to do this using Linq to SQL (assuming I had a sql table with your above schema). Since I spent the time figuring it out, I thought I might as well share it.
// Order the table and add an index column
var ordered = MonthTests.OrderBy(mt => mt.Date)
.AsEnumerable()
.Select((mt, index) => new
{
OrderId = index,
Record = mt
});
// Select out what we want
var query = from item in ordered
let prev = ordered.FirstOrDefault (q => q.OrderId == (item.OrderId-1))
select new
{
Title = item.Record.Title,
QuickLink = item.Record.QuickLink,
Date = item.Record.Date,
MonthName = (prev != null && prev.Record.MonthName == item.Record.MonthName) ? "" : item.Record.MonthName
};
Have fun.

How to get a particular row from a DataRow[]?

DataRow[] headerRows = null;
headerRows = mappingTable.Select("FieldID LIKE '0_%'"); //mappingTable is of type DataTable.
I have three columns in the mappingTable "Id","Display", "Value"
Now, I need to get the Value where "Id" = 0_0_0 from the headerRows.
Is there any simple way to do this?
Thanks for any help.
If you have to use DataRow[] then with linq you can do this:
String value = (String)rows.Single(
row => String.Equals(row["Id"], "0_0_0"))["Value"];
You need to set the PrimaryKey on the DataTable and then you can use Find() on the Rows collection to find the row with that key.
dataTable.PrimaryKey = new DataColumn[] { dataTable.Columns["Id"] };
object value = dataTable.Rows.Find("0_0_0")["Value"];
You could use LINQ: but this might be overkill:
dt.AsEnumerable().Where(dr => dr.Field<object>("FieldId").StartsWith("0_"));
If you have to have DataRow[] then
headerRows = dt.AsEnumerable().Where(dr => dr.Field<object>("FieldId").StartsWith("0_")).ToArray();
From there you have only data rows that match your criteria, so you can cycle through for the value.

Categories

Resources