Use a returned datatable - c#

I have two classes. I created a datatable in class 2 that gets returned. I am trying to figure out how I can use these values in class 1. I need to pass the datatable value in another method in class 1.
//Example:
In Class 2 I have:
public Datatable Mytable()
{
DataTable table = new DataTable();
table.Columns.Add("Column1", typeof(string));
table.Columns.Add("Column2", typeof(string));
//get values for the data row here
return table;
}
In Class 1 I have:
public Method1 (String A, String B)
//A and B need to represent the values in the Datatable from Class 2
{ string ab = "This is first datarow " + A + " This is second datarow " + B;
}

public class Class1 {
public Class1() {
var foo = new Class2();
var table = foo.MyTable();
Method1(table.Rows[0]["Column1"], table.Rows[0]["Column2"]);
}
}

I think you need to look up how to use DataTables here: http://www.dotnetperls.com/datatable-foreach

Related

Create ExpandoObject using Datatable

I am new to C# and gone through lot of questions in Stackoverflow.com and didn't find the solution for my requirement. So finally posting here.
My requirement is to create the dynamic properties from datatable column names and set the values to dynamic properties from datatable. and finally bind the data to gridview.
So I decided to follow below steps to achieve this functionality( kindly Correct me If I am wrong)
my datatable contains 26 rows and 10 columns of data
Create a Class A
Add dynamic properties to A from datatable(column names)
Set values to properties of A
Make class A to List of A
Bind List of A to GridView
I have done the below steps
1.
[Serializable]
public class A
{
public A()
{
}
}
2 & 3.
DataTable dt = getData();
dynamic expando = new ExpandoObject();
foreach (DataRow row in dt.Rows)
{
foreach (DataColumn col in dt.Columns)
{
var expandoDict = expando as IDictionary<String, Object>;
if (expandoDict.ContainsKey(col.ToString()))
expandoDict[col.ToString()] = row[col.ColumnName].ToString();
else
expandoDict.Add(col.ToString(), row[col.ColumnName].ToString());
}
}
After executing the above for loop, "expando" object contains only last row of datatable.
Can you please help me how to fix the steps 2 to 5.
From what I understand, this code may be more what you are looking for. This should get the data into the expandoList for you. You will then need to handle the binding to the GridView.
DataTable dt = getData();
List<dynamic> expandoList = new List<dynamic>();
foreach (DataRow row in dt.Rows)
{
//create a new ExpandoObject() at each row
var expandoDict = new ExpandoObject() as IDictionary<String, Object>;
foreach (DataColumn col in dt.Columns)
{
//put every column of this row into the new dictionary
expandoDict.Add(col.ToString(), row[col.ColumnName].ToString());
}
//add this "row" to the list
expandoList.Add(expandoDict);
}
Here's an extension method that would convert your datatable to list of Dynamic objects:
public static class DataTableExtension
{
public static IEnumerable<dynamic> AsDynamicEnumerable(this DataTable table)
{
// Validate argument here..
return table.AsEnumerable().Select(row => new DynamicRow(row));
}
private sealed class DynamicRow : DynamicObject
{
private readonly DataRow _row;
internal DynamicRow(DataRow row) { _row = row; }
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var retVal = _row.Table.Columns.Contains(binder.Name);
result = retVal ? _row[binder.Name] : null;
return retVal;
}
}
}
Usage: IEnumerable<dynamic> result = getData().AsEnumerable();

Fetch the value of nested structure returned by RFC?

I am new to C#. I have rfc that returns data from SAP system as nested structure but when I'am fetching that data using:
IrfcTable table = rfc.getTable("exporting_parameter"); // et_customer
it returns only first inner structure only.
For example my exporting internal table for rfc is
et_customer that contains sub structure as follow:
gen_data
bank data
tax data
it returns value inside gen_data only.
How to get entire data?
A couple of Extensions that may help. eg Convert from SAP structures to Other better known structures.
public static class SapToDataExtensionClass
{
public static Dictionary<string,string> ToDictionary(this IRfcStructure stru)
{
Dictionary<string,string> dict = new Dictionary<string, string>();
for (int i = 0; i < stru.Metadata.FieldCount; i++)
{
dict.Add(stru.Metadata[i].Name , stru.GetString(i) );
}
return dict;
}
public static DataTable GetDataTable(this IRfcTable i_Table)
{
DataTable dt = new DataTable();
dt.GetColumnsFromSapTable(i_Table);
dt.FillRowsFromSapTable(i_Table);
return dt;
}
public static void FillRowsFromSapTable(this DataTable i_DataTable, IRfcTable i_Table)
{
foreach (IRfcStructure tableRow in i_Table)
{
DataRow dr = i_DataTable.NewRow();
dr.ItemArray = tableRow.Select(structField => structField.GetValue()).ToArray();
i_DataTable.Rows.Add(dr);
}
}
public static void GetColumnsFromSapTable(this DataTable i_DataTable, IRfcTable i_SapTable)
{
var DataColumnsArr = i_SapTable.Metadata.LineType.CreateStructure().ToList().Select
(structField => new DataColumn(structField.Metadata.Name)).ToArray();
i_DataTable.Columns.AddRange(DataColumnsArr);
}
}

extracting contents of Datatable into list C#

I am experimenting to take datatable contents into a list. I am using following code but its not working correctly.
public List<object> ShowMessage()
{
List<object> obj = new List<object>();
DataTable dt = new DataTable();
dt.Columns.Add("ID");
dt.Columns.Add("Name");
dt.Rows.Add("1","AAA");
dt.Rows.Add("2", "BBB");
dt.Rows.Add("3", "CCC");
foreach (DataRow dr in dt.Rows)
{
obj.Add(dr);
}
return obj;
}
I am new and not sure I am doing in a right way or I need to use some thing else. Any suggestion will be highly appreciated.
Thanks.
Converting your DataTable to list of name strings (with help of Linq to DataSet):
List<string> names =
dt.AsEnumerable().Select(r => r.Field<string>("Name")).ToList();
Which is same as
List<string> names = new List<string>();
foreach(DataRow r in dt.Rows)
names.Add((string)r["Name"]);
I think you are making a too abstract example. This one use a possible class named Person
public class Person
{
public int PersonID;
public string Name;
// other fields will follow in future
}
public List<Person> GetPersonList()
{
List<Person> people = new List<Person>();
// This is just as example, because in real code
// you get this table from a database
DataTable dt = new DataTable();
dt.Columns.Add("ID");
dt.Columns.Add("Name");
dt.Rows.Add(1,"John");
dt.Rows.Add(2, "Mark");
dt.Rows.Add(3, "Steve");
// Loop over the rows and construct a Person instance for every row
// Add that row to the List<Person> to return
foreach (DataRow dr in dt.Rows)
{
Person p = new Person() {PersonID =Convert.ToInt32(dr[0]), Name = dr[1].ToString());
people.Add(p);
}
return people;
}
By the way, this pattern of code, is exactly what a good ORM do for you. A little research for Entity Framework or Dapper would be very useful
#Karni: you were close to what you need. however below is the modified version of your code example so that you achieve what you need..
public class Obj
{
public int ID { get; set; }
public string Name { get; set; }
}
public class ListObj : List<Obj>
{
}
class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("ID");
dt.Columns.Add("Name");
dt.Rows.Add("1", "AAA");
dt.Rows.Add("2", "BBB");
dt.Rows.Add("3", "CCC");
ListObj objListObj = new ListObj();
//to fill the list / collection
for (int i = 0; i < dt.Rows.Count; i++)
{
objListObj.Add(new Obj() { ID = Convert.ToInt16(dt.Rows[i][0]), Name = dt.Rows[i][1].ToString() });
}
//To verify if the collection is filled.
foreach (var item in objListObj)
{
Console.WriteLine(item.ID + " : " + item.Name);
}
Console.Read();
}
}

Find a row in a DataTable

I've a table in a DataSet and I want to search for a row in this Table using a unique key.
My question is : Is there any method that allows me to find this row without using loops ?
This is the code I wrote using the forech loop :
foreach (var myRow in myClass.ds.Tables["Editeur"].AsEnumerable())
{
if (newKeyWordAEditeurName == myRow[1] as String)
id_Editeur_Editeur = (int)myRow[0];
}
Sure. You have the Select method off of a DataTable. GEt the table from your DataSet, and use Select to snag it.
void Demo(DataSet ds)
{
DataTable dt = ds.Tables[0]; // refer to your table of interest within the DataSet
dt.Select("Field = 1"); // replace with your criteria as appropriate
}
To find a particular row, you might want to search by key which can uniquely identify each row.
But if you want to find a group of rows, then you want to use filter.
Key can contain different types of objects simultaneously. So can filter!
Following is a concrete example which covers searching with a key method or a filter method as locateOneRow() and locateRows() respectively.
using System.Data;
namespace namespace_A {
public static class cData {
public static DataTable srchTBL = new DataTable(tableName: "AnyTable");
public static DataColumn[] theColumns = {
new DataColumn("IDnum", typeof(int))
, new DataColumn("IDString", typeof(string))
, new DataColumn("DataString", typeof(string))
};
public static void DataInit(){
if (srchTBL.Columns.Count == 0) {
srchTBL.Columns.AddRange(theColumns);
srchTBL.PrimaryKey = new DataColumn[2] { srchTBL.Columns["IDnum"], srchTBL.Columns["IDstring"] };
//Data
srchTBL.Rows.Add(0, "me", "Homemaker");
srchTBL.Rows.Add(1, "me2", "Breadwinner2");
srchTBL.Rows.Add(1, "you", "Breadwinner1");
srchTBL.Rows.Add(2, "kid", "Learner");
}
}//DataInit
public static DataRow locateOneRow(){
DataInit();
object[] keyVals = new object[] {0, "me" };
return srchTBL.Rows.Find(keyVals);
}//locateOneRow - Result: the "Homemaker" row
public static DataRow[] locateRows(){ //no Primary key needed
DataInit();
return srchTBL.Select("IDnum = 1 OR IDstring = 'me'");
}//locateRows - Result: the row with "Homermaker" & the row with "Breadwinner2"
}//class
class Program {
static void Main(string[] args) {
try
{
DataRow row1 =cData.locateOneRow();
DataRow[] rows = cData.locateRows();
}catch(Exception ex){
}
} // Main
} // Program
}

Datatable subset of columns from another datatable

I have a datatable with 17 columns and a bunch of data.
I wnat a datatable with only 6 of the columns and the data for those 6 columns.
So I need a subset of the original datatable.
How do I loop through the original datatable with 17 columns and end up with a datatable with only the 6 columns I want with the corresponding data for those 6 columns?
Private Function createSmallCopyofExistingTable(ByVal SourceTable As DataTable) As DataTable
Dim newTable As DataTable = New DataTable()
'Copy Only 6 columns from the datatable
Dim ColumnsToExport() As String = {"ID", "FirstName", "LastName", "DateOfBirth", "City", "State"}
newTable = SourceTable.DefaultView.ToTable("tempTableName", False, ColumnsToExport)
Return newTable
End Function
Without knowing more about how generic this needs to be its really just...
foreach (DataRow dr in dt.Rows)
{
newDt.Rows.Add(dr["col1"],dr["col5"],etc);
}
what about data types, and columns? are these same? if yes, you can create
object[] row = new object[]{// Fill your rows manually};
before filling it create
DataTable dt = new DataTable();
dt.Columns.Add("Title",typeof(string etc..));.....
and finally
dt.Rows.Add(row);
Personally, I would avoid creating another instance of a DataTable.
It depends on your situation, of course, but if this is purely for usability and not for security (i.e. you're not trying to remove columns with sensitive data before transmitting it somewhere), then I would create a wrapper object that encapsulates the columns that you want to expose.
The benefit of using a wrapper is in case you are doing any updates, then you can update the source table directly rather than the copy. Whether this really matters, of course, depends on your situation.
A simple example with limited functionality:
public class MyFormOrPage
{
void UsageExample()
{
DataTable allDataTable = new DataTable();
// populate the data table with whatever logic ...
// wrap the data table to expose only the Name, Address, and PhoneNumber columns
var limitedDataTable = new DataTableWrapper(allDataTable, "Name", "Address", "PhoneNumber");
// iterate over the rows
foreach (var limitedDataRow in limitedDataTable)
{
// iterate over the columns
for (int i = 0; i < limitedDataTable.ColumnCount; i++)
{
object value = limitedDataRow[i];
// do something with the value ...
}
}
// bind the wrapper to a control
MyGridControl.DataSource = limitedDataTable;
}
}
public class DataTableWrapper : IEnumerable<DataRowWrapper>
{
private DataTable _Table;
private string[] _ColumnNames;
public DataTableWrapper(DataTable table, params string[] columnNames)
{
this._Table = table;
this._ColumnNames = columnNames;
}
public int ColumnCount
{
get { return this._ColumnNames.Length; }
}
public IEnumerator<DataRowWrapper> GetEnumerator()
{
foreach (DataRow row in this._Table.Rows)
{
yield return new DataRowWrapper(row, this._ColumnNames);
}
}
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
#endregion
// if you _really_ want to make a copy of the DataTable, you can use this method
public DataTable CopyToDataTable()
{
DataTable copyTable = new DataTable();
for (int index = 0; index < this._ColumnNames.Length; index++)
{
DataColumn column = this._Table.Columns[index];
copyTable.Columns.Add(column);
}
foreach (DataRow row in this._Table.Rows)
{
DataRow copyRow = copyTable.NewRow();
for (int index = 0; index < this._ColumnNames.Length; index++)
{
copyRow[index] = row[this._ColumnNames[index]];
}
copyTable.Rows.Add(copyRow);
}
return copyTable;
}
}
// let's make this a struct, since potentially very many of these will be instantiated
public struct DataRowWrapper
{
private DataRow _Row;
private string[] _ColumnNames;
public DataRowWrapper(DataRow row, params string[] columnNames)
{
this._Row = row;
this._ColumnNames = columnNames;
}
// use this to retrieve column values from a row
public object this[int index]
{
get { return this._Row[this._ColumnNames[index]]; }
set { this._Row[this._ColumnNames[index]] = value; }
}
// just in case this is still needed...
public object this[string columnName]
{
get { return this._Row[columnName]; }
set { this._Row[columnName] = value; }
}
}

Categories

Resources