Best practice when converting DataColumn values to an array of strings?
[Edit]
All values for certain DataColumn for all DataTable rows to be converted to an array of string?
If I understood your goal you want to specify a particular column and return all its values as a string array.
Try these approaches out:
int columnIndex = 2; // desired column index
// for loop approach
string[] results = new string[dt.Rows.Count];
for (int index = 0; index < dt.Rows.Count; index++)
{
results[index] = dt.Rows[index][columnIndex].ToString();
}
// LINQ
var result = dt.Rows.Cast<DataRow>()
.Select(row => row[columnIndex].ToString())
.ToArray();
You could replace columnIndex with columnName instead, for example:
string columnName = "OrderId";"
EDIT: you've asked for a string array specifically but in case you're flexible about the requirements I would prefer a List<string> to avoid the need to determine the array length prior to the for loop in the first example and simply add items to it. It's also a good opportunity to use a foreach loop instead.
I would then rewrite the code as follows:
List<string> list = new List<string>();
foreach (DataRow row in dt.Rows)
{
list.Add(row[columnIndex].ToString());
}
DataRow.ItemArray Property -
http://msdn.microsoft.com/en-us/library/system.data.datarow.itemarray.aspx
Also, which version are you using? You should check out the DataTableExtensions class -
http://msdn.microsoft.com/en-us/library/system.data.datatableextensions.aspx
And the DataRowExtensions class -
http://msdn.microsoft.com/en-us/library/system.data.datarowextensions.aspx
I know this question is old, but I found it in my Google search trying to do something similar. I wanted to create a list from all the values contained in a specific row of my datatable. In my code example below, I added a SQL datasource to my project in Visual Studio using the GUI wizards and I dropped the needed table adapter into the designer.
'Create a private DataTable
Private authTable As New qmgmtDataSet.AuthoritiesDataTable
'Fill the private table using the table adapter
Me.AuthoritiesTableAdapter1.Fill(Me.authTable)
'Make the list of values
Dim authNames As List(Of String) = New List(Of String)(From value As qmgmtDataSet.AuthoritiesRow In Me.authTable.Rows Select names.authName)
Related
This question already has answers here:
Remove Single Quotes From All Cells in a DataTable - Creating New Table - Using LINQ in Vb.Net
(2 answers)
Closed 3 years ago.
How to replace double quotes of all rows of DataTable using Linq in C#?
I tried below but I need more optimized code for same purpose
int columnIndex = 0;
dtExcelData.Rows.RemoveAt(0);
foreach (DataColumn excelSheetColumns in dtExcelData.Columns)
{
int rowIndex = 0;
foreach (DataRow row in dtExcelData.Rows)
{
dtExcelData.Rows[rowIndex][columnIndex] = dtExcelData.Rows[rowIndex][columnIndex].ToString().Replace("\"", "");
rowIndex++;
}
columnIndex++;
}
Please suggest
You could make use of DataRow.ItemArray. For example
foreach(var row in dtExcelData.Rows.Cast<DataRow>())
{
row.ItemArray = row.ItemArray.Select(x=>x.ToString().Replace("\"","")).ToArray();
}
You should
be aware you remove the first row, if you write results back to your data store you will lose this row.
ask yourself why you iterare over Columns and rows if you never use the objects. Why don't you simply use a for loop over rowIndex and columnIndex.
think about only processing data fields that really are a string.ToString() turns everything into a string, then you overwrite any kind of data field type with a string. Better test for "is String" and then cast the field into (String).
think about getting every row, then process every column in this row. This could be faster to execute, but even if it isn't then still is more understandable (at least to me).
I have added code here because code is better other than URL, You can try this below code:
That is already mentioned in below URL
Remove Single Quotes From All Cells in a DataTable - Creating New Table - Using LINQ in Vb.Net
dtExcelData.Rows.RemoveAt(0);
DataTable clone = dtExcelData.Clone();
string t;
var qry = from DataRow row in dtExcelData.Rows
let arr = row.ItemArray
select Array.ConvertAll(arr, s =>
(t = s as string) != null
&& t.StartsWith("\"")
&& t.EndsWith("\"") ? t.Trim('\"') : s);
foreach (object[] arr in qry)
{
clone.Rows.Add(arr);
}
I am trying to create a DataRow which gets some values from hard-coded strings or string variables, and the rest of the values from a collection's values, System.Collections.Generic.Dictionary<string, double>.ValueCollection to be specific. In my attempt below, I'm casting to an array but that doesn't work.
DataTable source = new DataTable();
foreach (string sample in GridSource.SampleName)
{
SampleDictionaries sd = GridSource.Data.Where(x => GridSource.Data.IndexOf(x) == GridSource.SampleName.IndexOf(sample)).First();
source.Rows.Add(sample, "Average", sd.Avg.Values.ToArray());
source.Rows.Add("", "Std. Deviation", sd.StdDev.Values.ToArray());
}
The code above produces this:
I understand what is happening here. My question is this: is there an easy way to tell the DataRow "Fill the remaining column values with this collection," or am I going to have to come up with some loop to do it?
what you can do is create the row from the datatable.NewRow() method. Then you can have the items array of the row equal an array of data:
DataTable source = new DataTable();
foreach (string sample in GridSource.SampleName)
{
DataRow temp = source.NewRow();
SampleDictionaries sd = GridSource.Data.Where(x => GridSource.Data.IndexOf(x) == GridSource.SampleName.IndexOf(sample)).First();
temp.ItemArray = new object[]{sample, "Average"}.Concat(sd.Avg.Values.ToArray());
source.Rows.Add(temp);
temp = source.NewRow();
temp.ItemArray = new object[]{"", "Std. Deviation".Concat(sd.StdDev.Values.ToArray());
}
Found an answer, with help from KMoussa!
source.Rows.Add(new object[] { "", "Std. Deviation"}.Concat(sd.StdDev.Values.Cast<object>().ToArray()).ToArray());
Very similar to what he recommended, but it was missing a second cast to array at the end.
I'm trying to perform the C# equivalent of Select * where [columnname] = [value]. I began with a foreach loop to iterate through the table row by row, however I had forgotten that one cannot access a column via row.column["<colname>"].
How do I achieve this objective? Most of the examples I have seen target one specific row with the intention of casting it's value to a string, however my task is to move all entries with a value of DateTime == < DateTime.Today to an archived table.
Can I continue with the following code? Or am I approaching this in the wrong manner?
void archiveDates()
{
foreach (DataRow row in workingupdates.storageTable.Rows)
{
//target DateTime column here
}
}
You can use the Field extension method that is strongly typed and also supports nullable types. You have an overload for the index, name or the DataColumn(among others):
foreach (DataRow row in workingupdates.storageTable.Rows)
{
DateTime dt = row.Field<DateTime>("columnname");
}
If you instead want to find all rows where the date column has a specific value you can use Linq-To-DataTable:
var matchingDataRows = workingupdates.storageTable.AsEnumerable()
.Where(row => row.Field<DateTime>("columnname") == dateTimeVariable);
Now you can simply enumerate this query:
foreach (DataRow row in matchingDataRows)
{
// ...
}
Or create a collection like
a DataRow[] with matchingDataRows.ToArray() or
a List<DataRow> with matchingDataRows.ToList()
a new DataTable with matchingDataRows.CopyToDataTable()
Note that you have to add System.Linq; to the top of the file.
I want to know if someone of you know a faster way to fill a DataTable manually then I do.
Here is what I got, I have a List with about 1.7b entries.
I want to fill this entries as fast as possible into DataTable with one column.
An entry in my list looks like this here {"A2C","DDF","ER","SQ","8G"}
My code need about 7-8 seconds
for (int i = 0; i <= lists.Count; i++)
{
table_list.Rows.Add();
}
for (int a = 0; a < list.Count; a++)
{
table_list.Rows[a][0] = list[a][0] + list[a][1] +
list[a][2] + list[a][3] + list[a][4];
}
As I didn't find any similar question on the board (just questions about how to fill datatable by sql and fill method), I decided to post my question.
Any input is highly appreciated!
i add this DataTable into an sql server database (i do this by SqlBulkCopy)
This is a mistake; the DataTable is pure overhead here. What you should expose is an IDataReader over that data. This API is a bit tricky, but FastMember makes it easier. For example, it sounds like you have 1 column; so consider:
class Foo {
public string ColumnName {get;set;}
}
Now write an iterator block method that converts this from the original list per item:
IEnumerable<Foo> Convert(List<TheOldType> list) {
foreach(var row in list) {
yield return new Foo { ColumnName = /* TODO */ };
}
}
and now create an IDataReader via FastMember on top of that lazy sequence:
List<TheOldType> list
var data = Convert(list);
using(var bcp = new SqlBulkCopy(connection))
using(var reader = ObjectReader.Create(data, "ColumnName"))
{
bcp.DestinationTableName = "SomeTable";
bcp.WriteToServer(reader);
}
This works much better than populating a DataTable - in particular, it avoids populating a huge DataTable. Emphasis: the above is spooling - not buffered.
Why do you create an empty row first, then loop the table again to fill them?
I would use a simple foreach:
var table_list = new DataTable();
table_list.Columns.Add();
foreach(string[] fields in lists)
{
DataRow newRow = table_list.Rows.Add();
newRow.SetField(0, string.Join("", fields));
}
Why do you put all into one field?
Why not use the LoadDataRow method of the DataTable.
// turnoff notifications
table_list.BeginLoadData();
// load each row into the table
foreach(string[] fields in lists)
table_list.LoadDataRow(new object[] { string.Join("", fields) }, false);
// turn notifications back on
table_list.EndLoadData();
Also see: DataTable.LoadDataRow Method http://msdn.microsoft.com/en-us/library/kcy03ww2(v=vs.110).aspx
I'm trying to transfer my datatable contents to another array. I am only going to get specific fields from the datatable, but I do not know how to save the specific columns content to another array.
What I did:
dr = SuperViewBLL.GetSomeStuff();
string[] new_array;
if (dr.Rows.Count > 0)
{
for (int i = 0; i < dr.Rows.Count;i++ )
{
new_array[i] = dr.Rows[i]['StuffLocationId'];
// I do know this is wrong
}
}
How can I get the column StuffLocationId to the array new_array?
That line is almost right, except that you need double quotes rather than single and you also need to cast/convert the value to type String to put it into a String array:
new_array[i] = (string) dr.Rows[i]["StuffLocationId"];
or, if the data is nullable:
new_array[i] = dr.Rows[i]["StuffLocationId"] as string;
The issue is that the array doesn't exist because you haven't created it. In order to create an array you have to know the size. If you haven't specified a size, either implicitly or explicitly, then you haven't created an array. This:
string[] new_array;
should be this:
string[] new_array = new string[dr.Rows.Count - 1];
You can also throw a bit of LINQ at the problem and succinctify the code a bit:
var new_array = dr.AsEnumerable()
.Select(row => row["StuffLocationId"] as string)
.ToArray();
That's also an example of specifying the size of the array implicitly.
This way is much more clear:
dt = SuperViewBLL.GetSomeStuff();
List<string> list = new List<string>();
foreach(DataRow row in dt.Rows)
{
list.Add((!row.IsNull("StuffLocationId") ? row["StuffLocationId"] as string : string.Empty));
}
Updated with the help of #jmcilhinney