My given problem is follow:
I have an object with x columns and every column has y values. I must now bring this into Excel.
I found a snippet in which a datatable can be exported easily. So I will bring my object to a datatable. How can I do this?
Language is C#
I'm not completely certain I know what you're trying to do. I assume you want to create a DataTable and load your existing object into it. Assuming your class looks something like this:
public class MyClass {
public int ID {get;set;}
public string Column1 {get;set;}
public DateTime Column2 {get;set;}
// ...
}
and assuming you have a list of them you want to copy into a DataTable, here's how:
DataTable dt = new DataTable("MyTable");
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Column1", typeof(string));
dt.Columns.Add("Column2", typeof(DateTime));
foreach (var o in _myObjectList) {
DataRow dr = dt.NewRow();
dr["ID"] = o.ID;
dr["Column1"] = o.Column1;
dr["Column2"] = o.Column2;
dt.Rows.Add(dr);
}
You can use reflection to get the fields of the object and add the columns to the DataTable:
private bool IsNullableType(Type theType)
{
return (theType.IsGenericType && theType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)));
}
// Create the columns based on the data in the album info - get by reflection
var ai = new <your object without data>;
Type t = ai.GetType();
this.dataTable.TableName = t.Name;
foreach (PropertyInfo p in t.GetProperties())
{
var columnSpec = new DataColumn();
// If nullable get the underlying type
Type propertyType = p.PropertyType;
if (IsNullableType(propertyType))
{
var nc = new NullableConverter(propertyType);
propertyType = nc.UnderlyingType;
}
columnSpec.DataType = propertyType;
columnSpec.ColumnName = p.Name;
this.dataTable.Columns.Add(columnSpec);
}
this.dataGridView.DataSource = dataTable;
Then to add a row to the table:
var info = new <your object with data>;
// Add by reflection
Type t = info.GetType();
var row = new object[t.GetProperties().Length];
int index = 0;
foreach (PropertyInfo p in t.GetProperties())
{
row[index++] = p.GetValue(info, null);
}
this.dataTable.Rows.Add(row);
Related
I am trying to reuse some code from a project that works with DataRow instead of object. In my new project I have the model created and I work all with objects but Im trying to bring that piece of code since its very large. So the question is how can I get a DataRow from an object.
class Person
{
public Int64 Id { get; set; }
public string Name { get; set; }
}
Person p1 = new Person();
p1.Id = 1;
p1.Name = "John";
// How to get a DataRow from this p1 object
drPerson["Id"] == 1
drPerson["Name"] == John
I am looking for a way to get done it automatically if that is possible
Thanks!
So finally thanks to the comments I got this code that works but it might be better
public static DataRow ToDataRow(object from) {
DataTable dt = new DataTable();
foreach(PropertyInfo property in from.GetType().GetProperties()) {
DataColumn column = new DataColumn();
column.ColumnName = property.Name;
column.DataType = property.PropertyType;
dt.Columns.Add(column);
}
DataRow dr = dt.NewRow();
foreach(PropertyInfo property in from.GetType().GetProperties()) {
dr[property.Name] = property.GetValue(from);
}
return dr;
}
With these code I can a DataRow with the name of the columns as the object atributes and also the values of it.
-- Edit
Usually DataRow objects don't just hang out by themselves. They will belong to a DataTable. This method is creating a throwaway DataTable just to make a row. - siride
That is right so I've changed it to this
public static DataRow ToDataRow(object from, DataTable dt) {
DataRow dr = dt.NewRow();
foreach(PropertyInfo property in from.GetType().GetProperties()) {
dr[property.Name] = property.GetValue(from);
}
return dr;
}
public static DataTable GetDataTable(object from) {
DataTable dt = new DataTable();
foreach(PropertyInfo property in from.GetType().GetProperties()) {
DataColumn column = new DataColumn();
column.ColumnName = property.Name;
column.DataType = property.PropertyType;
dt.Columns.Add(column);
}
return dt;
}
With this change I can retrieve the DataTable before getting the DataRow and use both
I wrote this cypher query in C#:
var myClint = new GraphClient(new Uri("http://localhost:7474/db/data"), "neo4j", "1412");
myClint.Connect();
var getName= myClint.Cypher.Match("(n:Person)
.Return(n => n.As<Person>())
.Results;
I have setters and getters in Person class to get the name, ssn, and age for everyone in the Person node. I want to display those information on a grid view. I did that with sql server but I do not know how to do it with neo4j.
Thanks in advance
https://stackoverflow.com/users/6771545/abd
In essence, you need to create your own DataTable, you can do it manually with code like this:
public static DataTable ConvertToTable(IEnumerable<Person> people)
{
DataTable dt = new DataTable();
dt.Columns.Add("Name");
dt.Columns.Add("Age");
foreach (var person in people)
{
var row = dt.NewRow();
row[0] = person.Name;
row[1] = person.Age;
dt.Rows.Add(row);
}
return dt;
}
But that means you have to write one of those for each type, so you can do this instead:
public static DataTable ConvertToTableAutomatic<T>(IEnumerable<T> items)
{
DataTable dt = new DataTable();
var properties = typeof(T).GetProperties();
foreach (var property in properties)
dt.Columns.Add(property.Name);
foreach (var item in items)
dt.Rows.Add(FillRow<T>(dt.NewRow(), item, properties));
return dt;
}
private static DataRow FillRow<T>(DataRow row, T item, PropertyInfo[] properties)
{
foreach (var property in properties)
row[property.Name] = property.GetValue(item);
return row;
}
But bear in mind - you won't be able to update the Neo4j DB with this, just display the information.
I'd like to use LINQ to take a datarow, and parse out the datacolumn names with their values.
So if I had a dataRow with the following columns and values:
DataColumn column1 with value '1'
DataColumn column2 with value 'ABC'
I'd like to have a string returned as "column1 = '1' and column2 = 'ABC'"
**** code should not care about the column names, nor the number of columns in the table.****
Purpose being, to filter a dataTable like:
var newRows = myTable.Select ("column1 = '1' and column2 = 'ABC'");
I can parse out the columns of the table like this:
string[] columnName = myTable.Columns.Cast<DataColumn>().Select(cn => cn.ColumnName).ToArray();
But I need to also extract values from a target row.
It feels like this might be a start:
{
string[] columnNames = existingTable.Columns.Cast<DataColumn>().Select(cn => cn.ColumnName).ToArray();
foreach (DataRow oldRow in existingTable.Rows)
{
var criteria = string.Join("and", columnNames, oldRow.ItemArray);
}
}
I think you are trying to get the column names and rows without actually referencing them. Is this what you're trying to do:
var table = new DataTable();
var column = new DataColumn {ColumnName = "column1"};
table.Columns.Add(column);
column = new DataColumn {ColumnName = "column2"};
table.Columns.Add(column);
var row = table.NewRow();
row["column1"] = "1";
row["column2"] = "ABC";
table.Rows.Add(row);
string output = "";
foreach (DataRow r in table.Rows)
{
output = table.Columns.Cast<DataColumn>()
.Aggregate(output, (current, c) => current +
string.Format("{0}='{1}' ", c.ColumnName, (string) r[c]));
output = output + Environment.NewLine;
}
// output should now contain "column1='1' column2='ABC'"
You can create extension methods out of this too, which operate both on a DataTable (for all rows) or a DataRow (for a single row):
public static class Extensions
{
public static string ToText(this DataRow dr)
{
string output = "";
output = dr.Table.Columns.Cast<DataColumn>()
.Aggregate(output, (current, c) => current +
string.Format("{0}='{1}'", c.ColumnName, (string)dr[c]));
return output;
}
public static string ToText(this DataTable table)
{
return table.Rows.Cast<DataRow>()
.Aggregate("", (current, dr) => current + dr.ToText() + Environment.NewLine);
}
}
I would highly recommend mapping to a class, and then adding another property which combines both of them!
See if this gets you in the right direction
EDIT Added solution using reflection since that is more in line with what you are wanting to accomplish
void Main()
{
List<MyClass> myColl = new List<MyClass>() { new MyClass() { myFirstProp = "1", mySecondProp = "ABC" } };
foreach (MyClass r in myColl)
{
List<string> rPropsAsStrings = new List<string>();
foreach (PropertyInfo propertyInfo in r.GetType().GetProperties())
{
rPropsAsStrings.Add(String.Format("{0} = {1}", propertyInfo.Name, propertyInfo.GetValue(r, null)));
}
Console.WriteLine(String.Join(" and ", rPropsAsStrings.ToArray()));
}
}
public class MyClass
{
public string myFirstProp { get; set; }
public string mySecondProp { get; set; }
}
The below uses Linq with strong typed properties
System.Data.DataTable table = new DataTable("ParentTable");
DataColumn column;
DataRow row;
column = new DataColumn();
column.DataType = typeof(string);
column.ColumnName = "column1";
table.Columns.Add(column);
column = new DataColumn();
column.DataType = typeof(string);
column.ColumnName = "column2";
table.Columns.Add(column);
row = table.NewRow();
row["column1"] = "1";
row["column2"] = "ABC";
table.Rows.Add(row);
var results = from myRow in table.AsEnumerable()
select String.Format("column1 = {0}, column2 = {1}", myRow[0], myRow[1]);
foreach (string r in results)
{
Console.WriteLine(r);
}
I am using .NET 3.5 and need to convert the below select new result into a DataTable. Is there something built in for this or anyone know of a method that can do this?
var contentList = (from item in this.GetData().Cast<IContent>()
select new
{
Title = item.GetMetaData("Title"),
Street = item.GetMetaData("Street"),
City = item.GetMetaData("City"),
Country = item.GetMetaData("Country")
});
Easy and straightforward thing to do is to use reflection:
var records = (from item in this.GetData().Cast<IContent>()
select new
{
Title = "1",
Street = "2",
City = "3",
Country = "4"
});
var firstRecord = records.First();
if (firstRecord == null)
return;
var infos = firstRecord.GetType().GetProperties();
DataTable table = new DataTable();
foreach (var info in infos) {
DataColumn column = new DataColumn(info.Name, info.PropertyType);
table.Columns.Add(column);
}
foreach (var record in records) {
DataRow row = table.NewRow();
for (int i = 0; i < table.Columns.Count; i++)
row[i] = infos[i].GetValue(record);
table.Rows.Add(row);
}
Code may not be working up front but should give you a general idea. First, you get propertyInfos from anonymous type and use this metadata to create datatable schema (fill columns). Then you use those infos to get values from every object.
Here is one generic solution without Reflecting over the properties. Have an extension method as below
public static DataTable ConvertToDataTable<TSource>(this IEnumerable<TSource>
records, params Expression<Func<TSource, object>>[] columns)
{
var firstRecord = records.First();
if (firstRecord == null)
return null;
DataTable table = new DataTable();
List<Func<TSource, object>> functions = new List<Func<TSource, object>>();
foreach (var col in columns)
{
DataColumn column = new DataColumn();
column.Caption = (col.Body as MemberExpression).Member.Name;
var function = col.Compile();
column.DataType = function(firstRecord).GetType();
functions.Add(function);
table.Columns.Add(column);
}
foreach (var record in records)
{
DataRow row = table.NewRow();
int i = 0;
foreach (var function in functions)
{
row[i++] = function((record));
}
table.Rows.Add(row);
}
return table;
}
And Invoke the same using where parameters will be the column name in the order you want.
var table = records.ConvertToDataTable(
item => item.Title,
item => item.Street,
item => item.City
);
You can convert your list result to datatable by the below function
public static DataTable ToDataTable<T>(IEnumerable<T> values)
{
DataTable table = new DataTable();
foreach (T value in values)
{
if (table.Columns.Count == 0)
{
foreach (var p in value.GetType().GetProperties())
{
table.Columns.Add(p.Name);
}
}
DataRow dr = table.NewRow();
foreach (var p in value.GetType().GetProperties())
{
dr[p.Name] = p.GetValue(value, null) + "";
}
table.Rows.Add(dr);
}
return table;
}
There is a CopyToDataTable extension method which does that for you. It lives in System.Data.DataSetExtensions.dll
Try this:
// Create your datatable.
DataTable dt = new DataTable();
dt.Columns.Add("Title", typeof(string));
dt.Columns.Add("Street", typeof(double));
// get a list of object arrays corresponding
// to the objects listed in the columns
// in the datatable above.
var result = from item in in this.GetData().Cast<IContent>()
select dt.LoadDataRow(
new object[] { Title = item.GetMetaData("Title"),
Street = item.GetMetaData("Street"),
},
false);
// the end result will be a set of DataRow objects that have been
// loaded into the DataTable.
Original Article for code sample : Converting Anonymous type generated by LINQ to a DataTable type
EDIT: Generic Pseudocode:
void LinqToDatatable(string[] columns, Type[] datatypes, linqSource)
{
for loop
{
dt.columns.add(columns[i], datatypes[i]);
}
//Still thinking how to make this generic..
var result = from item in in this.GetData().Cast<IContent>()
select dt.LoadDataRow(
new object[] { string[0] = item.GetMetaData[string[0]],
string[1] = item.GetMetaData[srring[1]
},
false);
}
public static DataTable ListToDataTable<T>(this IList<T> data)
{
DataTable dt = new DataTable();
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
for (int i = 0; i < props.Count; i++)
{
PropertyDescriptor prop = props[i];
dt.Columns.Add(prop.Name, prop.PropertyType);
}
object[] values = new object[props.Count];
foreach (T t in data)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = props[i].GetValue(t);
}
dt.Rows.Add(values);
}
return dt;
}
After you do your select new you can to .ToList().ListToDataTable(). This uses ComponentModel reflection and is (theroetically) faster than System.Reflection.
This works:
var Result = from e in actual.Elements
select new
{
Key = e.Key,
ValueNumber = e.Value.ValueNumber,
ValueString = e.Value.ValueString,
ValueBinary = e.Value.ValueBinary,
ValueDateTime = e.Value.ValueDateTime
};
But this doesn't work:
IEnumerable<DataRow> Result = from e in actual.Elements
select new DataRow
{
Key = e.Key,
ValueNumber = e.Value.ValueNumber,
ValueString = e.Value.ValueString,
ValueBinary = e.Value.ValueBinary,
ValueDateTime = e.Value.ValueDateTime
};
DataTable dt = Result.CopyToDataTable(Result);
Can you fix it for me? I want the second bit of code to work so that I can put it into the DataTable. I realize the syntax is totally wrong in #2. How do you specify a column using LINQ like this?
You can write a simple extension method that takes any IEnumerable<T>, uses reflection to get the PropertyDescriptors associated with T, and creates a DataColumn for each
public static DataTable PropertiesToDataTable(this IEnumerable<T> source)
{
DataTable dt = new DataTable();
var props = TypeDescriptor.GetProperties(typeof(T));
foreach (PropertyDescriptor prop in props)
{
DataColumn dc = dt.Columns.Add(prop.Name,prop.PropertyType);
dc.Caption = prop.DisplayName;
dc.ReadOnly = prop.IsReadOnly;
}
foreach (T item in source)
{
DataRow dr = dt.Rows.NewRow();
foreach (PropertyDescriptor prop in props)
dr[prop.Name] = prop.GetValue(item);
dt.Rows.Add(dr);
}
return dt;
}
I can't offer much help other than to point you here:
http://blogs.msdn.com/b/aconrad/archive/2007/09/07/science-project.aspx
You might want to look into the DataTableExtensions.AsEnumerable Method
I haven't tested this, but this might get you pointed in the right direction:
IEnumerable<DataRow> result = (from e in actual.Elements
select new DataRow
{
Key = e.Key,
ValueNumber = e.Value.ValueNumber,
ValueString = e.Value.ValueString,
ValueBinary = e.Value.ValueBinary,
ValueDateTime = e.Value.ValueDateTime
}).AsEnumerable();
DataTable dt = Result.CopyToDataTable(Result);