GetSchemaTable Columns Missing? - c#

I am using this code to get data from a dataReader into a DataTable which can then be serialised.
However, it looks like any column with a null value isnt being written to the xml.
I cant see the issue.
This is my entire class, and im calling this method
Process(IDataReader data, string filePath)
Im certain that this works, because i have used it to serialise dataTables before
Process(DataTable table, string filePath)
So i think it must be in the "GetDataTableFromSqlDataReader" method??
public class DataSerialisation
{
public static DataRow GetFirstDataRow(string xmlFilePath)
{
return GetDataTable(xmlFilePath).Rows[0];
}
public static DataTable GetDataTable(string xmlFilePath)
{
DataSet ds = new DataSet();
ds.ReadXml(xmlFilePath);
return ds.Tables[0];
}
private static DataTable GetDataTableFromSqlDataReader(IDataReader dr)
{
DataTable dtSchema = dr.GetSchemaTable();
DataTable dt = new DataTable();
ArrayList listCols = new ArrayList();
if (dtSchema != null)
{
foreach (DataRow drow in dtSchema.Rows)
{
string columnName = Convert.ToString(drow["columnName"]); //drow["columnName"].ToString();
DataColumn column = new DataColumn(columnName, (Type) (drow["DataType"]));
//column.ColumnName = columnName;
//column.Unique = (bool) (drow["IsUnique"]);
column.AllowDBNull = (bool) (drow["AllowDBNull"]);
//column.AutoIncrement = (bool) (drow["IsAutoIncrement"]);
//column.AutoIncrement = (bool) (drow["IsAutoIncrement"]);
listCols.Add(column);
dt.Columns.Add(column);
}
while (dr.Read())
{
DataRow dataRow = dt.NewRow();
for (int i = 0; i < listCols.Count; i++)
dataRow[((DataColumn) listCols[i])] = dr[i];
dt.Rows.Add(dataRow);
}
}
return dt;
}
public static void Process(IDataReader data, string filePath)
{
Process(GetDataTableFromSqlDataReader(data), filePath);
}
public static void Process(DataTable table, string filePath)
{
DataSet ds = new DataSet();
ds.Tables.Add(table.Clone());
foreach (DataRow row in table.Rows)
{
DataRow newRow = ds.Tables[0].NewRow();
for (int col = 0; col < ds.Tables[0].Columns.Count; col++)
newRow[col] = row[col];
ds.Tables[0].Rows.Add(newRow);
}
ds.WriteXml(new StreamWriter(filePath));
}
}

Related

'row' argument cannot be null.Parameter name: row

I am trying to load back values from a CSV to my class. Then display the values to my datatable. However, I get the error even after my values have been loaded into the class and placed inside the intended columns (See Figure 1). The error occurred at dt.Rows.Add(dr);. Below is my code:
public Newdatagrid()
{
InitializeComponent();
//Do datatable
ds = new DataSet();
dt = new DataTable();
dt.Columns.Add("Bus Model", typeof(string));//0
dt.Columns.Add("Bus Type", typeof(string));//1
dt.Columns.Add("Mileage", typeof(string));//2
if (Savestate.vehnochange_list.Count > 0)
{
foreach (DataRow dr in dt.Rows)
{
dr["Bus Model"] = Savestate.busmodel_list[Savestate.busmodel_list.Count];//0
dr["Bus Type"] = Savestate.bustype_list[Savestate.bustype_list.Count];//1
dr["Mileage"] = Savestate.busmileage_list[Savestate.busmileage_list.Count];//2
}
dt.Rows.Add(dr);
this.dataGridView2.DataSource = dt;
}
}
I think you want something like this:
public Newdatagrid()
{
InitializeComponent();
//Do datatable
ds = new DataSet();
dt = new DataTable();
dt.Columns.Add("Bus Model", typeof(string));//0
dt.Columns.Add("Bus Type", typeof(string));//1
dt.Columns.Add("Mileage", typeof(string));//2
if (Savestate.vehnochange_list.Count > 0)
{
for (int i=0; i < Savestate.vehnochange_list.Count; ++i)
{
DataRow dr = dt.NewRow();
dr["Bus Model"] = Savestate.busmodel_list[i];//0
dr["Bus Type"] = Savestate.bustype_list[i];//1
dr["Mileage"] = Savestate.busmileage_list[i];//2
dt.Rows.Add(dr);
}
this.dataGridView2.DataSource = dt;
}
}

How to add data continuity in DataTable?

I want to continue to add data to datatable that already contains data.
In this method, it was get data like: dt = { 1, 2 }.
public class GetRowOne()
{
// some code
if(contains == null)
{
DataRow dr = dt.NewRow();
string[] array1 = lstHeader[1].ToArray();
for (int i = 0; i < 8; i++)
dr[i] = array1[i];
}
// some code
}
dt.Rows.Add(dr.ItemArray);
Now, in another method, I also create and run same like this code.
public class GetRowTwoAndThree()
{
// some code
DataRow dr = dt.NewRow();
string[] array1 = lstHeader[1].ToArray();
for (int i = 0; i < 8; i++)
dr[i] = array1[i];
// some code
}
dt.Rows.Add(dr.ItemArray);
It return new values in dt is: dt = { 4, 5 }
I think error at like: DataRow dr = dt.NewRow(); or line: dt.Rows.Add(dr.ItemArray);
You will look: when dt.Rows.Add(dr.ItemArray). All before data will null, it only add new values to dt.
I want dt save old data and new data, it should be:
dt = { 1, 2, 3, 4 }
Store Data in ViewState["OldData"] and after adding new row again store dt in ViewState["OldData"].
If in same page you are calling method then store that in viewstate, you can also store in session or create get set method for that datatable
DataTable dt{get; set;}
EDIT-:
DataTable dt = new DataTable();
public Form1()
{
InitializeComponent();
dt.Columns.Add("Column1");
dttest = dt;
}
public void GetRowOne()
{
DataRow dr = dt.NewRow();
dr["Column1"] = "Test";
dt.Rows.Add(dr);
dttest = dt;
}
DataTable dttest { get; set; }
private void button1_Click(object sender, EventArgs e)
{
GetRowOne();
}

hashtable datagridview show empty lines

My Datagrid is filled with the right number of rows, but there are no data show.
All the row are display empty cols.
What could be the reason for that ?
basedon
It is the first time I use a datagridview.
public void BindDataGridView(DataGridView dgv, Hashtable ht) {
DataSet ds = new DataSet();
DataTable dt = ds.Tables.Add("test");
//now build our table
dt.Columns.Add("col1", typeof(string));
dt.Columns.Add("col2", typeof(Int32));
IDictionaryEnumerator enumerator = ht.GetEnumerator();
DataRow row = null;
while (enumerator.MoveNext()) {
string index = (string)enumerator.Key; // boekingsREf
MyClass a = (MyClass)enumerator.Value;
row = dt.NewRow();
row["col1"] = index;
row["col2"] = a.number;
dt.Rows.Add(row);
}
//dgv.DataSource = ds.Tables[0];
dgv.DataSource = ds.Tables[0];
}
First example:
public Form1()
{
InitializeComponent();
Hashtable ht = new Hashtable();
ht[1] = "One";
ht[2] = "Two";
ht[3] = "Three";
BindDataGridView(dataGridView1, ht);
}
public void BindDataGridView(DataGridView dgv, Hashtable ht)
{
DataSet ds = new DataSet();
DataTable dt = ds.Tables.Add("test");
//now build our table
dt.Columns.Add("col1", typeof(int));
dt.Columns.Add("col2", typeof(string));
foreach (DictionaryEntry dictionaryEntry in ht)
{
int index = (int)dictionaryEntry.Key;
string value = (string)dictionaryEntry.Value;
DataRow row = dt.NewRow();
row["col1"] = index;
row["col2"] = value;
dt.Rows.Add(row);
}
dgv.DataSource = ds.Tables[0];
}
Second example:
Assuming your MyClass is
public class MyClass
{
public int number { get; set; }
static public implicit operator MyClass(int value)
{
return new MyClass() { number = value };
}
}
and the hashtable is (reverse keys/values)
Hashtable ht = new Hashtable();
ht["One"] = 1;
ht["Two"] = 2;
ht["Three"] = 3;
and you change this line from your post code
MyClass a = (int)enumerator.Value;

Convert datatable to datareader

For Performance improvement I want to convert datatable to datareader. I can not do that through query. So is there any other way to do so?
I know this is old, but the answers here seem to have missed the point of the OPs question.
DataTables have a method called CreateDataReader which will allow you to convert a DataTable to a DbDataReader object. In this case a DataTableReader.
DataTable table = new DataTable();
//Fill table with data
//table = YourGetDataMethod();
DataTableReader reader = table.CreateDataReader();
I should point out that this will not increase performance since you should be using one or the other.
Here are some more resources on the matter:
DataReader Vs DataTable
Is datareader quicker than dataset when populating a datatable?
For example
public DataTable ConvertDataReaderToDataTable(SqlDataReader dataReader)
{
DataTable datatable = new DataTable();
DataTable schemaTable = dataReader.GetSchemaTable();
try
{
foreach (DataRow myRow in schemaTable.Rows)
{
DataColumn myDataColumn = new DataColumn();
myDataColumn.DataType = myRow.GetType();
myDataColumn.ColumnName = myRow[0].ToString();
datatable.Columns.Add(myDataColumn);
}
while (dataReader.Read())
{
DataRow myDataRow = datatable.NewRow();
for (int i = 0; i < schemaTable.Rows.Count; i++)
{
myDataRow[i] = dataReader[i].ToString();
}
datatable.Rows.Add(myDataRow);
myDataRow = null;
}
schemaTable = null;
return datatable;
}
catch (Exception ex)
{
Error.Log(ex.ToString());
return datatable;
}
}
Use DataTable constructor,
DataTable table = new DataTable();
//Fill table with data
DataTableReader reader = new DataTableReader(table);
Good Look!
public DataTable GetTable(IDataReader _reader)
{
DataTable dataTable1 = _reader.GetSchemaTable();
DataTable dataTable2 = new DataTable();
string[] arrayList = new string[dataTable1.Rows.Count];
for (int i = 0; i < dataTable1.Rows.Count; i++)
{
DataColumn dataColumn = new DataColumn();
if (!dataTable2.Columns.Contains(dataTable1.Rows[i]["ColumnName "].ToString()))
{
dataColumn.ColumnName = dataTable1.Rows[i]["ColumnName "].ToString();
dataColumn.Unique = Convert.ToBoolean(dataTable1.Rows[i]["IsUnique "]);
dataColumn.AllowDBNull = Convert.ToBoolean(dataTable1.Rows[i]["AllowDBNull "]);
dataColumn.ReadOnly = Convert.ToBoolean(dataTable1.Rows[i]["IsReadOnly "]);
dataColumn.DataType = (Type)dataTable1.Rows[i]["DataType "];
arrayList[i] = dataColumn.ColumnName;
dataTable2.Columns.Add(dataColumn);
}
}
dataTable2.BeginLoadData();
while (_reader.Read())
{
DataRow dataRow = dataTable2.NewRow();
for (int j = 0; j < arrayList.Length; j++)
{
dataRow[arrayList[j]] = _reader[arrayList[j]];
}
dataTable2.Rows.Add(dataRow);
}
_reader.Close();
dataTable2.EndLoadData();
return dataTable2;
}

Convert and use DataTable in WPF DataGrid?

In normal WinForm application you can do that:
DataTable dataTable = new DataTable();
dataTable = dataGridRecords.DataSource;
but how to do that with the WPF datagrid?
dataTable = dataGridRecords.ItemsSource;
won't work either.
In WPF you don't do this
DataGrid.ItemsSource = DataTable;
Instead you do
DataGrid.ItemsSource = DataTable.AsDataView();
In order to get DataTable back you can do something like this
public static DataTable DataViewAsDataTable(DataView dv)
{
DataTable dt = dv.Table.Clone();
foreach (DataRowView drv in dv)
dt.ImportRow(drv.Row);
return dt;
}
DataView view = (DataView) dataGrid.ItemsSource;
DataTable table = DataViewAsDataTable(view)
You don't need the DataViewAsDataTable method. Just do the following:
DataTable dt = ((DataView)dataGrid1.ItemsSource).ToTable();
try this
public static DataTable DataGridtoDataTable(DataGrid dg)
{
dg.SelectAllCells();
dg.ClipboardCopyMode = DataGridClipboardCopyMode.IncludeHeader;
ApplicationCommands.Copy.Execute(null, dg);
dg.UnselectAllCells();
String result = (string)Clipboard.GetData(DataFormats.CommaSeparatedValue);
string[] Lines = result.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
string[] Fields;
Fields = Lines[0].Split(new char[] { ',' });
int Cols = Fields.GetLength(0);
DataTable dt = new DataTable();
for (int i = 0; i < Cols; i++)
dt.Columns.Add(Fields[i].ToUpper(), typeof(string));
DataRow Row;
for (int i = 1; i < Lines.GetLength(0)-1; i++)
{
Fields = Lines[i].Split(new char[] { ',' });
Row = dt.NewRow();
for (int f = 0; f < Cols; f++)
{
Row[f] = Fields[f];
}
dt.Rows.Add(Row);
}
return dt;
}

Categories

Resources