3

I'm new ExpandoObject (indeed, i found out about it yesterday). I have the following code and wonder if there is a method of some sort to convert ExpandoObject to a DataTable that I'm not aware of? Or i have to use reflection to convert it myself?

dynamic contacts = new List<dynamic>();

contacts.Add(new ExpandoObject());
contacts[0].Name = "Patrick Hines";
contacts[0].Phone = "206-555-0144";

contacts.Add(new ExpandoObject());
contacts[1].Name = "Ellen Adams";
contacts[1].Phone = "206-555-0155";
NKD
  • 1,039
  • 1
  • 13
  • 24
  • 1
    `ExpandoObject` implements `IDictionary`, so you can use whatever code you would use to convert a dictionary to a `DataTable`. – Jeroen Mostert Dec 05 '14 at 16:40

2 Answers2

6

Here is what I have to convert it. But if anyone has a better method, please let me know.

    public DataTable ToDataTable(IEnumerable<dynamic> items)
    {
        var data = items.ToArray();
        if (data.Count() == 0) return null;

        var dt = new DataTable();
        foreach (var key in ((IDictionary<string, object>)data[0]).Keys)
        {
            dt.Columns.Add(key);
        }
        foreach (var d in data)
        {
            dt.Rows.Add(((IDictionary<string, object>)d).Values.ToArray());
        }
        return dt;
    }
NKD
  • 1,039
  • 1
  • 13
  • 24
  • This works as long as your objects all have the same properties (otherwise, divining the table structure is a bit more difficult). But if they do, why use `ExpandoObject` in the first place? You can just declare a class to hold your data, which has positive effects on maintainability as well. `class Contact { public string Name { get; set; } public string Phone { get; set; } }` isn't that much to type. – Jeroen Mostert Dec 05 '14 at 16:53
  • Perhaps I can get some help from you to better structure my code. I am dealing with a list of complex model which is a list within a list. My reason for having a sublist inside a model because the selection is a multiselect, which return a list of ids. I need to flatten it out a datatable then do a bulk copy to db. Hence, create a dynamic object of this model with a new property to hold a concat string of ids. The concat string of ids eventually stored in a column/field in db as 1,2,3. I'm open up to suggestion to flatten nested list to a datable. – NKD Dec 05 '14 at 17:18
  • that sounds like a very specific scenario that needs a bit more than what we can do in comments. Try [Code Review](http://codereview.stackexchange.com/). – Jeroen Mostert Dec 05 '14 at 19:00
0

You can use this code. Linq will help you :)

var contacts = new List<dynamic>();

contacts.Add(new ExpandoObject());
contacts[0].Name = "Patrick Hines";
contacts[0].Phone = "206-555-0144";

contacts.Add(new ExpandoObject());
contacts[1].Name = "Ellen Adams";
contacts[1].Phone = "206-555-0155";
// DataTable Instance...
DataTable table = new DataTable();

//Get all properties of contract list items
var properties = contacts.GetType().GetProperties();

// Remove contract list property
properties = properties.ToList().GetRange(0, properties.Count() - 1).ToArray();

// Add column as named by property name
properties.ToList().ForEach(p => table.Columns.Add(p.Name,typeof(string)));

// Add rows from contracts list
contacts.ForEach(x =>  table.Rows.Add(x.Name,x.Phone));
  • Nice work with LINQ. I went with the other option because I want to reuse the method in the future. Your method work just fine but I don't want to retype it if I need to convert something else. (i.e. specify the property name x.Name, x.Phone.) Thank you for taking your time to look into this. – NKD Dec 05 '14 at 17:30