Getting datarow values into a string? - c#

I have a dataset called "results" with several rows of data. I'd like to get this data into a string, but I can't quite figure out how to do it. I'm using the below code:
string output = "";
foreach (DataRow rows in results.Tables[0].Rows)
{
output = output + rows.ToString() + "\n";
}
However, I think I'm missing something because this isn't working. Can someone point me in the right direction?

You need to specify which column of the datarow you want to pull data from.
Try the following:
StringBuilder output = new StringBuilder();
foreach (DataRow rows in results.Tables[0].Rows)
{
foreach (DataColumn col in results.Tables[0].Columns)
{
output.AppendFormat("{0} ", rows[col]);
}
output.AppendLine();
}

I've done this a lot myself. If you just need a comma separated list for all of row values you can do this:
StringBuilder sb = new StringBuilder();
foreach (DataRow row in results.Tables[0].Rows)
{
sb.AppendLine(string.Join(",", row.ItemArray));
}
A StringBuilder is the preferred method as string concatenation is significantly slower for large amounts of data.

You can get a columns value by doing this
rows["ColumnName"]
You will also have to cast to the appropriate type.
output += (string)rows["ColumnName"]

Your rows object holds an Item attribute where you can find the values for each of your columns. You can not expect the columns to concatenate themselves when you do a .ToString() on the row.
You should access each column from the row separately, use a for or a foreach to walk the array of columns.
Here, take a look at the class:
http://msdn.microsoft.com/en-us/library/system.data.datarow.aspx

Related

(C#) Can I fill a column in a group of rows of a DataTable with a certain value, only if they meet a certain criteria, using LINQ?

Iterating through a group of DataRows and filling the DataColumn in question with the value is taking too much time.
I have a DataTable with various DataColumns, one of the particular columns is ("DieID", typeof(string).
I have an array DataRow[] binningRows of DataRows of this DataTable that have certain DieIDs in that column. This array is the result of a Table Filter Expression.
I have to fill a different column (not "DieID") of all of these DataRows in binningRows with the same value, but this takes a long time because of the number of tables and their number of DataRows. Is there a way to do this with LINQ instead of a for/foreach loop? Willing to sacrifice more readability
Currently I am doing this sequence: Get List of DieIDs from filter -> Use List of DieIDs to get array
DataRows[] binningRows with proper DieIDs -> Iterate through Array of binningRows and fill proper column with value.
Code Sample:
List<string> dieIDs = table.Select(filter)
.AsEnumerable()
.Select(x => x["DieID"].ToString())
.Distinct()
.ToList();
foreach (string die in dieIDs)
{
DataRow[] binningRows = table.Select("DieID = '" + die + "'");
if (binningRows.Length == 1)
{
binningRows[0][paramIndex] = int.Parse(binList.Key);
}
//else handle duplicate error **Was ruled out as cause of slowing**
}
This is clearly inefficient even though it is only hitting each row once.
I am going to begin exploring default List values as an option. I am already filling other columns with defaults and adding row by row (a bit different requirements but it is much faster), but struggled with it initially here because of issues with ordering and the fact that paramIndex is different columns each time
Potentially I could do something like
Dictionary<string, List<string>> paramDefaults;
foreach (string param in paramNames)
{
paramDefaults.Key = param;
paramDefaults.Value.AddRange(Enumerable.Repeat(string.Join(",", DieID,binList.Key)), count).ToList();
}
// code
// code
// code
for (int i = 0; i < numDieTested; i++)
{
wafer.Value.waferData.Tables["Binning"].Rows.Add(waferID[i], dieID[i], devices[i],
paramDefaults[param1].Value, paramDefaults[param2].Value, paramDefaults[param3].Value
);
}
However, I dont think this will quite work due to paramDefaults[param1].Value correct? Anything close to this?

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.

C# Linq from DataTable

I have a small DataTable that contains a number of rows which I am running a LINQ query against.
I am having problems getting the LINQ to display the text that is in the datatable.
When I run it I can get the column name.
I have tried a number of different ways of doing it but to no avail.
Code as follows:
DataTable DTGetNarratives = DAL.GetNarrativeList();
var SelectedNarrative =
from n in DTGetNarratives.AsEnumerable()
where n.Field<string>("narr_code").Equals(ClsPublic.NarrativeCode)
select n;
foreach (var item in SelectedNarrative)
{
//test1.Add(item.Table.Columns[col].ToString());
//col++;
txtLine1.Text = item.Table.Columns[0].DefaultValue.ToString();
}
Any help on this would be great.
So you have one TextBox but an IEnumerable<DataRow>. Do you expect a single row? If not, how do you want to diplays multiple records on a single textbox?
You could comma separate them:
var allNarrCode = SelectedNarrative.Select(r => r.Field<string>("narr_code"));
txtLine1.text = string.Join(",", allNarrCode);
or as multiline TextBox use the Lines property:
txtLine1.Lines = allNarrCode.ToArray();
Only the first:
txtLine1.Text = SelectedNarrative.FirstOrDefault();
without LINQ:
foreach (DataRow row in SelectedNarrative)
{
string code = row.Field<string>("narr_code")
// the next line is pointless since you're overwriting the text on every row
//txtLine1.Text = code;
}
You can use the Field extension method like:
foreach (var item in SelectedNarrative)
{
txtLine1.Text = item.Field<string>("narr_code"); //here
}
(You can specify the column name in the method parameters)
I am not sure if you really need that since your TextBox would be populated with the last row's value.
To show all values in a single TextBox you can do:
txtLine1.Text = string.Join(" ",SelectedNarrative.Select(r=> r.Field<string>("narr_code")));
Or you can do
StringBuilder sb = new StringBuilder();
foreach (var item in SelectedNarrative)
{
sb.Append(item.Field<string>("narr_code"));
}
txtLine1.Text = sb.ToString();

Extract a value from Datatable and store to a collection in c#

I want to extract a value from the datatable and store to a collection. What would be the best way to do it?
The rows in my Datatable will have data like :
Row 1 <configuration><Store parameter="Atribs">AB,CD</Store></configuration>
Row 2 <configuration><Store parameter="Atribs">EF,GH,IJ</Store></configuration>
......
I want to retrieve and store the values in a collection like,
Collection 1 :
AB
CD
Collection 2 :
EF
GH
IJ
Collection ....
Here you go...
var table = new DataTable();
var column = new DataColumn("col1");
table.Columns.Add(column);
var row = table.NewRow();
row[0] = #"<configuration><Store parameter=""Atribs"">AB,CD</Store></configuration>";
table.Rows.Add(row);
row = table.NewRow();
row[0] = #"<configuration><Store parameter=""Atribs"">EF,GH,IJ</Store></configuration>";
table.Rows.Add(row);
var data = new List<List<string>>();
foreach (DataRow dRow in table.Rows)
{
var temp = new List<string>();
string xml = dRow.Field<string>("col1");
var element = XElement.Parse(xml);
string[] values = element.Descendants("Store").First().Value.Split(',');
temp.AddRange(values);
data.Add(temp);
}
You say a DataTable, but provided xml data in your example, so I am not sure.. bu basically, this is what you need to do:
var myList = new List<string>();
foreach (DataRow row in dataTable.Rows)
{
myList.Add(row.Field<string>("myCol"));
}
Something like that. It would be easier to give a better example if you could provide us with info about your DataTable and not your source xml file. :)
You might need to be a bit more clear on what you mean by "datatable" in that your example data is XML. Provided you know enough to fetch the rows from the data/xml:
Read each row and use String.Split() on the inner value to generate a string array which can be fed into a List.
var list = new List<string>(String.Split(",", innerData));
Of course you'll want to validate that the inner data has content.

DataTable.DefaultView.Sort Doesn't Sort

I am confused on DataTable.DefaultView.Sort. Here is the segment of the code I want to use it in.
actionLogDT.DefaultView.Sort = "StartDate";
foreach (CustomerService.ActionLogStartEndRow logRow in actionLogDT)
{
// code here
}
The samples I have seen don't use the foreach loop and thus is confusing me on how to process this. It isn't sorting as I thought it should be.
I see that .DefaultView returns a view, and .Table gives a compile error.
actionLogDT.DefaultView.Sort = "StartDate";
actionLogDT = actionLogDT.DefaultView.ToTable();
Sorting the view won't change the sort order of the data in the table, just the order in the view. It should work if you do your foreach on the view instead, casting the row from the DataRowView back to your strongly typed row.
foreach (DataRowView logRowView in actionLogDT.DefaultView)
{
CustomerService.ActionLogStartEndRow logRow = logRowView.Row as CustomerService.ActionLogStartEndRow;
// code here
}
I had to take a slightly different approach. This post was the closest I could find to get my code to work. Here is the working result:
actionLogDT.DefaultView.Sort = "StartDate";
DataView dv = actionLogDT.DefaultView;
foreach (DataRowView logRow in dv) { . . . }
From there I just have to cast the value back into it's proper type.
(string)logRow["Status"].ToString()
foreach (var logRow in actionLogDT.DefaultView.ToDataTable()) { ... }
Additionally, Since it seemed like you wanted to loop through records, you can just loop through the dataRowView objects in the DefaultView.
foreach (DataRowView drv in table.DefaultView)
{
string strValue = drv["ColumnName"].ToString();
// its also worth mentioning that a DataRowView has a Row
strValue = drv.Row["ColumnName"].ToString();
}
Please try this:
actionLogDT.DefaultView.Sort = "["+actionLogDT.Columns[0].ColumnName+"] asc";
Just curious: Why are you using the DataRowView?
i.e.
foreach (DataRow row in actionLogDT.Rows)
{
Console.WriteLine(row["Status"]);
}
If you need a datatable back then you can do something like:
var dv = actionLogDT.DefaultView;
dv.Sort = "StartDate";
actionLogDT = dv.ToTable();
In VB.NET, the code below was the best way for me to invoke the solution. Just copy your origtable to a DataView, and then the dataview can be sorted with a simple .sort command, and then set a new table equal to the sorted view (of your original table). Use the sorted table dt for your processing thereafter.
Dim View1 As DataView = New DataView(origtable)
View1.Sort = "LastName"
Dim dt As DataTable = View1.ToTable

Categories

Resources