Reputation: 125
I have searched high and low for a method to show the entire row of a C# datatable, both by referencing the row number and by simply writing the row contents to a string variable and showing the string in the console. I can specify the exact row and field value and display that value, but not the whole row. This is not a list in C#, this is a datatable.
For the simple code below, the output I get for the first WriteLine is "Horse", but the second two WriteLine commands, I get the console output of "System.Data.DataRow" instead of the whole row of data.
What am I doing wrong? Any help would be appreciated.
using System;
using System.Data;
using System.Threading;
namespace DataTablePractice
{
class Program
{
static void Main(string[] args)
{
// Create a DataTable.
using (DataTable table = new DataTable())
{
// Two columns.
table.TableName = "table";
table.Columns.Add("Number", typeof(string));
table.Columns.Add("Pet", typeof(string));
// ... Add two rows.
table.Rows.Add("4", "Horse");
table.Rows.Add("10", "Moose");
// ... Display first field of the first row in the console
Console.WriteLine(table.Rows[0].Field<string>(1));
//...Display the first row of the table in the console
Console.WriteLine(table.Rows[0]);
//...Create a new row variable to add a third pet
var newrow = table.Rows.Add("15", "Snake");
string NewRowString = newrow.ToString();
//...Display the new row of data in the console
Console.WriteLine(NewRowString);
//...Sleep for a few seconds to examine output
Thread.Sleep(4000);
}
}
}
}
Upvotes: 2
Views: 5376
Reputation: 2080
While the answer here is excellent, I highly recommend using Spectre.Console
It is an open source library that helps you generate highly formatted console output. With this, the code to write the output simply becomes:
public static void Print(this DataTable dataTable)
{
var table = new Table();
table.AddColumn("#");
for (int i=0;i<dataTable.Columns.Count;i++)
{
table.AddColumn(dataTable.Columns[i].ColumnName);
}
for(int i=0;i<dataTable.Rows.Count;i++)
{
var values = new List<string>
{
i.ToString()
};
for (int j = 0; j < dataTable.Columns.Count;j++)
{
values.Add(dataTable.Rows[i][j]?.ToString()??"null");
}
table.AddRow(values.ToArray());
}
AnsiConsole.Write(table);
}
Upvotes: 0
Reputation: 66489
When you run this:
Console.WriteLine(table.Rows[0]);
It's in effect calling this:
Console.WriteLine(table.Rows[0].ToString()); // prints object type, in this case a DataRow
If it were your own class, you could override ToString to return whatever you need, but you don't have that option with the DataRow
class. And so it uses the default behavior as described here:
Default implementations of the Object.ToString method return the fully qualified name of the object's type.
You could iterate through the columns, like this for example:
var row = table.Rows[0];
for (var i = 0; i < row.Count; i++)
Console.Write(row[i] + " : ");
Or, a shorter way to print them all out:
Console.WriteLine(String.Join(" : ", table.Rows[0].ItemArray));
Given your data, maybe you just want to reference the two fields?
foreach (DataRow row in dt.Rows)
Console.WriteLine($"You have {row[0]} {row[1]}(s).");
// You have 4 Horse(s).
// You have 10 Moose(s).
Upvotes: 3