extracting contents of Datatable into list C# - 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();
}
}

Related

How to melt a DataTable in C# .NET (wide to long format)?

How to melt a DataTable in C# (wide to long format) as Python Pandas.melt does? https://pandas.pydata.org/docs/reference/api/pandas.melt.html
Is there any method already implemented? If not, how the code for melting a DataTable would
For example:
I have one DataTable which is in wide format, that is that has one row per id and has as many columns as variables. I would like to transform this DataTable to long format that has as many rows as combinations of id with each variable column. You can see this example in top image.
Please, if there is not clear enough visit Pandas documentation, there is more clear. (https://pandas.pydata.org/docs/reference/api/pandas.melt.html)
Note: I would like a solution that is DataTable independent, that is, that the solution is able to take parameters as id_vars, value_vars, etc... like Pandas.melt does
Any help is appreciated.
I don't know that Melt method but according to docs it seems to be an unpivot method:
public static DataTable MeltTable(DataTable inputTable, string outputColumn, params string[] unpivotColumns)
{
DataTable resultTable = new DataTable();
DataColumn col = new DataColumn(outputColumn, inputTable.Columns[outputColumn].DataType);
resultTable.Columns.Add(col);
resultTable.Columns.Add("Variable");
resultTable.Columns.Add("Value");
foreach(string unpivotColumn in unpivotColumns)
{
foreach (DataRow row in inputTable.Rows)
{
resultTable.Rows.Add(row[outputColumn], unpivotColumn, row[unpivotColumn]);
}
}
return resultTable;
}
You use it in this way:
DataTable table = new DataTable();
table.Columns.Add("Name");
table.Columns.Add("Course");
table.Columns.Add("Age", typeof(int));
table.Rows.Add("Tim", "Masters", 47);
table.Rows.Add("Bob", "Graduate", 19);
table.Rows.Add("Sheila", "Graduate", 20);
DataTable resultTable = MeltTable(table, "Name", "Course", "Age");
Result:
Name Variable Value
Tim Course Masters
Bob Course Graduate
Sheila Course Graduate
Tim Age 47
Bob Age 19
Sheila Age 20
#TimSchmelter gave me the answer but I modified a little bit to be a more general solution. Here's the code:
public static List<string> GetDifferenceColumns(DataTable dt, List<string> diffCols)
{
string[] columns = GetColumnsList(dt).ToArray();
IEnumerable<string> differenceColumns = from column in columns.Except(diffCols.ToArray()) select column;
return differenceColumns.ToList();
}
public static DataTable Melt(DataTable dt, List<string> idCols = null, List<string> varCols = null)
{
string errorPrefixString = "Error in DataProcessing Melt Method:\n";
bool varsColsIsNull = (varCols == null || varCols.Count == 0);
bool idColsIsNull = (idCols == null || idCols.Count == 0);
string varsName = "Variable";
string valueName = "Value";
if (dt.Rows.Count == 0)
{
throw new Exception(errorPrefixString + "DataTable is empty");
}
if (varsColsIsNull && varsColsIsNull)
{
throw new Exception(errorPrefixString+"You should past at least varCols or idCols");
}
if (varsColsIsNull)
{
varCols = GetDifferenceColumns(dt, idCols);
}
if (idColsIsNull)
{
idCols = GetDifferenceColumns(dt, varCols);
}
DataTable resultTable = new DataTable();
// Creating final columns of resultTable
foreach (string id in idCols)
{
resultTable.Columns.Add(id);
}
resultTable.Columns.Add(varsName);
resultTable.Columns.Add(valueName);
// Populating resultTable with the new rows
// generated by unpivoting varCols
foreach (string varCol in varCols)
{
foreach (DataRow row in dt.Rows)
{
DataRow resultRow = resultTable.NewRow();
foreach(string id in idCols)
{
resultRow[id] = row[id]; // create id cols
}
resultRow[varsName] = varCol;
resultRow[valueName] = row[varCol];
resultTable.Rows.Add(resultRow);
}
}
return resultTable;
}
How to use it:
DataTable dt = new DataTable();
dt.Columns.Add("Name");
dt.Columns.Add("Course");
dt.Columns.Add("Age");
dt.Rows.Add("Tim", "Masters", 47);
dt.Rows.Add("Bob", "Graduate", 19);
dt.Rows.Add("Sheila", "Graduate", 20);
List<string> varCols = new List<string> { "Course", "Age" };
DataTable finalDataTable = Melt(dt, varCols: varCols);

Problem with filling a Table in c# from a list

I am working with WindowsForm and C# and I am filling out a List<> and everything is fine so far
In my list<> I have 103 records but when I pass to my DataTable no record appears only the headers, that is to say that when I receive my table everything shows in null
The truth is, I'm a little new to this and it's the first one that I'm working on.
List<MSProject.Task> tasks = new List<MSProject.Task>();
DataTable Tabla = new DataTable();
Tabla = ListToDataTable(tasks);
my code
public static DataTable ListToDataTable<T>(IList<T> data)
{
DataTable table = new DataTable();
//special handling for value types and string
if (typeof(T).IsValueType || typeof(T).Equals(typeof(string)))
{
DataColumn dc = new DataColumn("Value");
table.Columns.Add(dc);
foreach (T item in data)
{
DataRow dr = table.NewRow();
dr[0] = item;
table.Rows.Add(dr);
}
}
else
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
foreach (PropertyDescriptor prop in properties)
{
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
}
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
{
try
{
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
}
catch (Exception ex)
{
row[prop.Name] = DBNull.Value;
}
}
table.Rows.Add(row);
}
}
return table;
}
Thanks in advance
I've run your code and it's work, The problem I believe is that the MSProject.Task doesn't have any public properties and you are iterating only in properties. PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
see the code below:
//with properties
public class MSProject.Task
{
public string Name {get; set;}
public string code {get; set;}
}
//no properties
public class MSProject.Task2
{
public string Name;
public string code;
}
private void ShowRownsInGrid()
{
//it works shows rows in DataGridView!
List<MSProject.Task> tasks = new List<MSProject.Task>()
{
new MSProject.Task(){ Name = "Joao", code = "01215452124"},
new MSProject.Task(){ Name = "Maria", code = "4564678"},
};
DataTable Tabla = new DataTable();
Tabla = ListToDataTable(tasks);
MessageBox.Show(Tabla.Rows.Count.ToString()); //Show '2'
dataGridView1.DataSource = Tabla; //Show 2 rows
}
private void DontShowRownsInGrid()
{
//it doesn't work, no rows are displayed in the DataGridView!
List<MSProject.Task2> tasks = new List<MSProject.Task2>()
{
new MSProject.Task2(){ Name = "Joao", code = "01215452124"},
new MSProject.Task2(){ Name = "Maria", code = "4564678"},
};
DataTable Tabla = new DataTable();
Tabla = ListToDataTable(tasks);
MessageBox.Show(Tabla.Rows.Count.ToString()); //Show '2'
dataGridView1.DataSource = Tabla; //does not show lines
}

How to evaluate a DataColumn expression faster?

I created a class that's responsible to evaluate an expression values for the row when I need it but the problem that when my methods works very slow in big datatables.
public static class RowExpressionEvaluator
{
public static object EvaluateValue(DataRow row, string expression, Type outputType)
{
if (row == null) throw new ArgumentNullException(nameof(row));
return EvaluateValue(row.Table, row, expression, outputType);
}
private static object EvaluateValue(DataTable table, DataRow row, string expression, Type outputType)
{
if (table == null) throw new ArgumentNullException(nameof(table));
if (row == null) throw new ArgumentNullException(nameof(row));
if (string.IsNullOrEmpty(expression)) throw new ArgumentException("Expression cannot be null or empty.", nameof(expression));
if (row.RowState.Equals(DataRowState.Detached)) throw new ArgumentException(#"The rowState is detached.");
object result = null;
using (var tempColumn = new DataColumn("Exp", outputType))
{
table.Columns.Add(tempColumn);
tempColumn.Expression = expression;
if (!row[tempColumn.ColumnName].IsDbNull())
result = row[tempColumn.ColumnName];
table.Columns.Remove(tempColumn);
}
return result;
}
}
This code works fine but its slow when the datatable contains big data
I tried to improve this code so when I have many expressions to evaluate
then when I finish I dispose it it works better but still needs to improve because I think when I add the column with an expression the datatable evaluate it for all the rows but I need to evaluate the value only for the passed row.
like this one :
public sealed class BetterRowExpressionEvaluator :IDisposable
{
private readonly DataRow _row;
private readonly DataColumn _expressionColumn;
public BetterRowExpressionEvaluator(DataRow row)
{
_row = row ?? throw new ArgumentNullException(nameof(row));
if (row.RowState.Equals(DataRowState.Detached)) throw new ArgumentException(#"The rowState is detached.");
_expressionColumn = new DataColumn("Expression",typeof(object));
DataTable table = _row.Table;
table.Columns.Add(_expressionColumn);
}
public object Evaluate(string expression)
{
if (string.IsNullOrEmpty(expression)) throw new ArgumentException("Value cannot be null or empty.", nameof(expression));
_expressionColumn.Expression = expression;
return !_row[_expressionColumn.ColumnName].IsDbNull() ? _row[_expressionColumn.ColumnName] : null;
}
public void Dispose()
{
if (_expressionColumn == null) return;
DataTable table = _row.Table;
table.Columns.Remove(_expressionColumn);
_expressionColumn?.Dispose();
}
}
I did something like this to clone the row and it's parent and child relations so when I evaluate the expressions it comes faster and this is what I did :
private DataSet CloneTableWithRelations(DataRow row)
{
var dataset = new DataSet("EvaluationDataSet") {Locale = CultureInfo.InvariantCulture};
dataset.Tables.Add(row.Table.Clone());
dataset.Tables[row.Table.TableName].ImportRow(row);
foreach (DataRelation parentRelation in row.Table.ParentRelations)
{
string relationName = parentRelation.RelationName;
DataTable parentTable = parentRelation.ParentTable;
// clone the parent table
dataset.Tables.Add(parentTable.Clone());
// copy the parent rows related only to the passed row
DataRow parentRow= row.GetParentRow(relationName);
dataset.Tables[parentTable.TableName].ImportRow(parentRow);
DataColumn parentColumn=parentRelation.ParentColumns[0];
DataColumn childColumn=parentRelation.ChildColumns[0];
dataset.Relations.Add(relationName, parentColumn, childColumn,false);
}
foreach (DataRelation dataRelation in row.Table.ChildRelations)
{
DataTable childTable = dataRelation.ChildTable;
// clone the parent table
dataset.Tables.Add(childTable.Clone());
// copy the parent rows related only to the passed row
foreach (DataRow childRow in row.GetChildRows(dataRelation.RelationName))
{
dataset.Tables[childTable.TableName].ImportRow(childRow);
}
DataColumn parentColumn=dataRelation.ParentColumns[0];
DataColumn childColumn=dataRelation.ChildColumns[0];
dataset.Relations.Add(dataRelation.RelationName, parentColumn, childColumn,false);
}
return dataset;
}
is there a better way to do it and more reliable way ?
Finally It works much better
when I clone the row and its parent and child data
using this class I've created
public class RowCloneHandler
{
private readonly DataRow _row;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "<Pending>")]
public RowCloneHandler(DataRow row)
{
_row = row ?? throw new ArgumentNullException(nameof(row));
if (row.RowState.Equals(DataRowState.Detached)) throw new ArgumentException("The rowState is detached.");
}
public DataSet CloneToDataSet()
{
var ClonedDataset = new DataSet { Locale = CultureInfo.InvariantCulture };
DataTable clonedMainTable = _row.Table.Clone();
ClonedDataset.Tables.Add(clonedMainTable);
ClonedDataset.Tables[_row.Table.TableName].ImportRow(_row);
CloneParentTablesToDataset(ClonedDataset, clonedMainTable);
CloneChildTablesToDataSet(ClonedDataset, clonedMainTable);
return ClonedDataset;
}
private void CloneChildTablesToDataSet(DataSet clonedDataset, DataTable clonedMainTable)
{
foreach (DataRelation dataRelation in _row.Table.ChildRelations)
{
DataTable childTable = dataRelation.ChildTable;
// clone the parent table
DataTable clonedChildTable = childTable.Clone();
// copy the parent rows related only to the passed row
foreach (DataRow childRow in _row.GetChildRows(dataRelation.RelationName))
{
clonedChildTable.ImportRow(childRow);
}
clonedDataset.Tables.Add(clonedChildTable);
DataColumn parentColumn = clonedMainTable.Columns[dataRelation.ParentColumns[0].ColumnName];
DataColumn childColumn = clonedChildTable.Columns[dataRelation.ChildColumns[0].ColumnName];
clonedDataset.Relations.Add(dataRelation.RelationName, parentColumn, childColumn, false);
}
}
private void CloneParentTablesToDataset(DataSet clonedDataset, DataTable clonedMainTable)
{
foreach (DataRelation parentRelation in _row.Table.ParentRelations)
{
DataTable parentTable = parentRelation.ParentTable;
// clone the parent table
DataTable clonedParentTable = parentTable.Clone();
// copy the parent rows related only to the passed row
DataRow parentRow = _row.GetParentRow(parentRelation.RelationName);
clonedParentTable.ImportRow(parentRow);
clonedDataset.Tables.Add(clonedParentTable);
DataColumn parentColumn = clonedParentTable.Columns[parentRelation.ParentColumns[0].ColumnName];
DataColumn childColumn = clonedMainTable.Columns[parentRelation.ChildColumns[0].ColumnName];
clonedDataset.Relations.Add(parentRelation.RelationName, parentColumn, childColumn, false);
}
}
}
You need to create a clone of your DataTable, import the DataRow to the cloned DataTable, and then add the computed column in the cloned DataTable. Here are some extension methods that do exactly that.
Update: I revised the code to take into account the existing relations with other tables. The code became much more complicated because now the cloned table must be placed inside the existing DataSet, and the existing relations must be also cloned, and temporary renamed. The cloned relations are created without constraints, so hopefully the performance will not be negatively affected.
public static class DataRowExtensions
{
public static object Compute(this DataRow dataRow, string expression)
{
using (var clonedDT = CloneDataTable(dataRow))
{
clonedDT.ImportRow(dataRow);
var clonedRow = clonedDT.Rows[0];
var dataColumn = clonedDT.Columns.Add(null, typeof(object), expression);
return clonedRow[dataColumn];
}
}
public static T Compute<T>(this DataRow dataRow, string expression)
{
using (var clonedDT = CloneDataTable(dataRow))
{
clonedDT.ImportRow(dataRow);
var clonedRow = clonedDT.Rows[0];
var dataColumn = clonedDT.Columns.Add(null, typeof(T), expression);
return clonedRow.Field<T>(dataColumn);
}
}
public static T? ComputeNullable<T>(this DataRow dataRow, string expression)
where T : struct
{
using (var clonedDT = CloneDataTable(dataRow))
{
clonedDT.ImportRow(dataRow);
var clonedRow = clonedDT.Rows[0];
var dataColumn = clonedDT.Columns.Add(null, typeof(T), expression);
return clonedRow.Field<T?>(dataColumn);
}
}
private static DataTable CloneDataTable(DataRow dataRow)
{
var dataTable = dataRow.Table;
var dataSet = dataRow.Table.DataSet;
if (dataSet == null) return dataTable.Clone();
var clonedDT = dataSet.Tables.Add();
foreach (DataColumn column in dataTable.Columns)
{
clonedDT.Columns.Add(column.ColumnName, column.DataType);
}
var relationsAdded = new List<
(DataRelation Cloned, DataRelation Original)>();
foreach (var relation in dataTable.ParentRelations
.Cast<DataRelation>().ToArray())
{
var relationName = relation.RelationName;
relation.RelationName = Guid.NewGuid().ToString();
var clonedColumns = relation.ChildColumns
.Select(c => clonedDT.Columns[c.ColumnName]).ToArray();
var clonedRelation = dataSet.Relations.Add(relationName,
relation.ParentColumns, clonedColumns, createConstraints: false);
relationsAdded.Add((clonedRelation, relation));
}
foreach (var relation in dataTable.ChildRelations
.Cast<DataRelation>().ToArray())
{
var relationName = relation.RelationName;
relation.RelationName = Guid.NewGuid().ToString();
var clonedColumns = relation.ParentColumns
.Select(c => clonedDT.Columns[c.ColumnName]).ToArray();
var clonedRelation = dataSet.Relations.Add(relationName,
clonedColumns, relation.ChildColumns, createConstraints: false);
relationsAdded.Add((clonedRelation, relation));
}
clonedDT.Disposed += (s, e) => // Cleanup
{
clonedDT.Rows.Clear();
foreach (var entry in relationsAdded)
{
dataSet.Relations.Remove(entry.Cloned);
entry.Original.RelationName = entry.Cloned.RelationName;
}
clonedDT.Columns.Clear();
dataSet.Tables.Remove(clonedDT);
};
return clonedDT;
}
}
Usage example:
var dt = new DataTable();
dt.Columns.Add("Price", typeof(decimal));
dt.Rows.Add(10);
decimal doublePrice = dt.Rows[0].Compute<decimal>("Price * 2");
Console.WriteLine(doublePrice);
Output:
20

Fill Data To a particular Cell In DataTable -C#

I have data like
ConcurrentDictionary<string, ConcurrentDictionary<string,string> OneTwoThree =
new ConcurrentDictionary<string, ConcurrentDictionary<string, string>();
I want a result like this Final Image
What I tried:
DataTable dt = new DataTable();
dt.Columns.Add("TwoDetails");
ISet<string> two = new HashSet<string>();
Parallel.ForEach(OneTwoThree , One=>
{
dt.Columns.Add(One.Key);
foreach(var Two in One.Value)
{
two.Add(Two.Key); // To get Distinct Values
}
});
foreach(var item in two)
{
var row = dt.NewRow();
row["TwoDetails"] = row;
}
Now I don't have the idea to append "Three-Values" to a particular cell, as shown in the image.
Any Suggestions.
Another pivot table question. Done a 1000. See code below :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication31
{
class Program
{
static void Main(string[] args)
{
Dictionary<string, Dictionary<string, string>> OneTwoThree = new Dictionary<string, Dictionary<string, string>>() {
{"A", new Dictionary<string,string>(){{"U","s"}, {"Z","a"}}},
{"B", new Dictionary<string,string>(){{"W","e"},{"X","d"},{"Y","d"}}},
{"C", new Dictionary<string,string>(){{"V","f"}, {"W","a"},{"Z","w"}}},
};
string[] columns = OneTwoThree.Select(x => x.Key).OrderBy(x => x).ToArray();
DataTable dt = new DataTable();
dt.Columns.Add("TwoDetails", typeof(string));
foreach(string column in columns)
{
dt.Columns.Add(column, typeof(string));
}
string[] rows = OneTwoThree.Select(x => x.Value.Select(y => y.Key)).SelectMany(x => x).Distinct().OrderBy(x => x).ToArray();
var flip = rows.Select(x => new { row = x, columns = OneTwoThree.Where(y => y.Value.ContainsKey(x)).Select(y => new { col = y.Key, value = y.Value[x] }).ToList() }).ToList();
//create pivot table
foreach (var row in flip)
{
DataRow newRow = dt.Rows.Add();
newRow["TwoDetails"] = row.row;
foreach (var column in row.columns)
{
newRow[column.col] = column.value;
}
}
}
}
}
You can not access the data table rows with their names but using row numbers you can find a particular row in the data table.So for that, You need to create one class like
public class DataTableDetails
{
public string RowName { get; set; }
public int RowNumber { get; set; }
}
And this is not effecient solution, but can help you
ISet<string> two = new HashSet<string>();
List<DataTableDetails> dtdetaills=new List<DataTableDetails>();
Parallel.ForEach(OneTwoThree , One=>
{
dt.Columns.Add(One.Key);
foreach(var Two in One.Value)
{
two.Add(Two.Key); // To get Distinct Values
}
});
int count=0;
foreach(var item in two)
{
var row = dt.NewRow();
row["TwoDetails"] = row;
DataTableDetails details = new DataTableDetails();
details.RowName = item;
details.RowNumber = count++; // we can easily get row number
dtdetails.Add(details);
}
And Finally
foreach(var One in OnrTwoThree)
{
foreach(var Two in One.Value)
{
foreach(var rowdetails in dtdetails)
{
if(Two.Key==rowdetails.RowName)
{
dt.Rows[rowdetails.RowNumber][One.Key] = Two.Value;
}
}
}
}

OleDb / DataTable to Model

have to extract data from a mdb file on the server. I can open and access the data. Now i have to map it to a model and i have no Idea how to receive the data as a model. My idea was to loop through the received DataTabel data and assign it to values of the model type:
OleDbCommand command = new OleDbCommand(sqlcommand, DbConnection);
adapter = new OleDbDataAdapter(command);
builder = new OleDbCommandBuilder(adapter);
dt = new DataTable();
try
{
DbConnection.Open();
adapter.Fill(dt);
foreach (DataRow row in dt.Rows)
{
var examplemodel= new exampleModel(
Id = row.ItemArray[0],
...
);
}
}
catch (Exception ex)
{
}
finally
{
DbConnection.Close();
}
The problem here is that I can not assign row.ItemArray[x] as an element of the model since row.ItemArray[x] is of type object and I cannot convert it to a int string or whatever.
Also I thought that there is maybe a simpler and cleaner approach to this problem.
Any ideas or suggestion are much appreciated.
You can use this
var Entity=(from DataRow dataRow in data.Rows select YourEntity<exampleModel>(dataRow)).ToList();
The Helper Class
public static T YourEntity<T>(DataRow row) where T : new()
{
var entity = new T();
var properties = typeof(T).GetProperties();
foreach (var property in properties)
{
//Get the description attribute
var descriptionAttribute = (DescriptionAttribute)property.GetCustomAttributes(typeof(DescriptionAttribute), true).SingleOrDefault();
if (descriptionAttribute == null)
continue;
property.SetValue(entity, row[descriptionAttribute.Description]);
}
return entity;
}
and Decorate the Entity with proper datatable header
public class exampleModel
{
....
[Description("Subentity_datatable_header_header")]
public string Subentity { get; set; }
....
}
I prefer simple Linq. Whatever approach it may be, it is very clean and safe if we use the column names instead of index.
You could do something like.
dt.Rows.AsEnumerable()
.Select(r=> new exampleModel()
{
Id = r.Field<int>("col1"),
Name = r.Field<string>("col2"),
...
});

Categories

Resources