Feed a LINQ result into a DataROW - c#

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);

Related

How-to convert a dictionary to a datatable?

Using C#, how-to convert a dictionary to a datatable?
There is an example on how-to convert a list into a datatable at
Convert generic List/Enumerable to DataTable?
I started working on this, since 2019-12-17.
And, I have searched, Google, Stackoverflow, and Microsoft websites.
public static DataTable DictionaryToDataTable<T>(this IDictionary<K, V> data)
{
PropertyDescriptorCollection propertiesK = TypeDescriptor.GetProperties(typeof(K));
PropertyDescriptorCollection propertiesV = TypeDescriptor.GetProperties(typeof(V));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in propertiesK)
table.Columns.Add(prop.Name,
Nullable.GetUnderlyingType(prop.PropertyType)
?? prop.PropertyType);
foreach (PropertyDescriptor prop in propertiesV)
table.Columns.Add
(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType)
?? prop.PropertyType);
foreach(KeyValuePair<K, V> item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in propertiesK)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
foreach (PropertyDescriptor prop in propertiesV)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
}
Type ex = typeof(InformationInTransit.ProcessLogic.DataTableHelper);
MethodInfo mi = ex.GetMethod("DictionaryToDataTable");
MethodInfo miConstructed =
mi.MakeGenericMethod
(
typeof
(
Dictionary
<
String,
InformationInTransit.ProcessLogic.Exact.Participation
>
)
);
object[] args = {result};
DataTable dataTable = (DataTable) miConstructed.Invoke
(
null,
args
);
one attempt would simply be something like this:
Dictionary<int,int> dictionary=new Dictionary<int, int>();
DataTable dt=new DataTable();
dt.Columns.Add("Key", typeof(int));
dt.Columns.Add("Val", typeof(int));
foreach (var item in dictionary)
{
DataRow dr = dt.NewRow();
dr["Key"] = item.Key;
dr["Val"] = item.Value;
dt.Rows.Add(dr);
}
once try this: (nameList and globalVariable are list)
var dictionary = nameList.Zip(globalVariable, (k, v) => new { Key = k, Value = v })
.ToDictionary(x => x.Key, x => x.Value);
DataTable dt = new DataTable();
dt.Columns.Add("Variable names", typeof(string));
dt.Columns.Add("Variable values", typeof(string));
foreach (var pair in dictionary)
{
DataRow dr = dt.NewRow();
dr["Variable names"] = pair.Key;
dr["Variable values"] = pair.Value;
dt.Rows.Add(dr);
}
You might find it more convenient to write this as a generic for a Dictionary of any types. As a further refinement, you can make it as an Extension Method. Something like this:
public static class Extensions
{
public static DataTable ConvertToDataTable<TKey, TValue>(this Dictionary<TKey, TValue> data, string colName1, string colName2)
{
var dT = new DataTable();
dT.Columns.Add(colName1, typeof(TKey));
dT.Columns.Add(colName2, typeof(TValue));
foreach (var kVP in data)
{
var nR = dT.NewRow();
nR[0] = kVP.Key;
nR[1] = kVP.Value;
dT.Rows.Add(nR);
}
return dT;
}
}
It can be called simply by
var dT = myDictionary.ConvertToDataTable("keyColumnName", "valueColumnName");

Converting LINQ Join query to DataTable

I want to convert the LINQ Join query result into the DataTable for which I have checked but couldn't found any authentic solution.
I have tried to do it two ways
1:
var query = from A in ABC.AsEnumerable()
join X in XYZ.AsEnumerable()
on A.Field<int>("A-ID") equals
X.Field<int>("X-ID")
where ((A.Field<string>("A-Column1") == "1")
&& (r.Field<string>("X-Column1") == "1"))
select new
{
UserName = ABC.Field<string>("UserName"),
UserExperience = XYZ.Field<string>("UserExperience"),
...
};
2:
DataTable dt = new DataTable();
dt.Columns.Add("UserName", typeof(string));
dt.Columns.Add("UserExperience", typeof(string));
var query = from A in ABC.AsEnumerable()
join X in XYZ.AsEnumerable()
on A.Field<int>("A-ID") equals
X.Field<int>("X-ID")
where ((A.Field<string>("A-Column1") == "1")
&& (r.Field<string>("X-Column1") == "1"))
select dt.LoadDataRow(new object[]
{
ABC.Field<string>("UserName"),
XYZ.Field<string>("UserExperience"),
...
}, false);
DataTable ddt = new DataTable();
ddt = query.CopyToDataTable();
But that both couldn't resolve my problem.
I want to convert that result into the DataTable / DataSet.
Thanks in advance.
Create the following method and pass any type of object your LINQ query returning.
public static DataTable CreateDataTableFromAnyCollection<T>(IEnumerable<T> list)
{
Type type = typeof(T);
var properties = type.GetProperties();
DataTable dataTable = new DataTable();
foreach (PropertyInfo info in properties)
{
dataTable.Columns.Add(new DataColumn(info.Name, Nullable.GetUnderlyingType(info.PropertyType) ?? info.PropertyType));
}
foreach (T entity in list)
{
object[] values = new object[properties.Length];
for (int i = 0; i < properties.Length; i++)
{
values[i] = properties[i].GetValue(entity,null);
}
dataTable.Rows.Add(values);
}
return dataTable;
}
and pass your LINQ result like
DataTable dt = CreateDataTableFromAnyCollection(list);
Hope this will help you.

C# List<string>[] to Datatable

I need to convert a list array of type List<string>[] to Datatable in C#.
I have found many topics related to List<string[]> to Datatable conversion but nothing on the conversion I need.
Pseudocode:
//Retrieve data from MySQL server
db.Select(category, productID);
//populate List<string>[] array
list[0] = db.ListQuery[0];
list[1] = db.ListQuery[1];
//convert list[] to Datatable
.....
Any help is much appreciated.
If I'm understanding your question right, do you mean something like this?
string category = "Category";
string productId = "ProductId";
List<string[]> tempList = db.Select(category, productID); //Not necessarily correct (I'm not familiar with MySQL). Do what you need to do to create the List<string[]>
DataTable table = new DataTable();
DataRow row;
table.Columns.Add(category);
table.Columns.Add(productId);
foreach (string[] s in tempList)
{
row = table.NewRow();
row[category] = s[0];
row[productId] = s[1];
table.Rows.Add(row);
}
DataTable dataTable = new DataTable();
List<MemberInfo> props = typeof(T).GetFields().Select(objField => (MemberInfo)objField).ToList();
props.AddRange(typeof(T).GetProperties().Select(objField => (MemberInfo)objField));
if (props.Count > 0)
{
Type t;
bool tIsField = false;
for (int iCnt = 0; iCnt < props.Count; iCnt++)
{
var prop = props[iCnt];
tIsField = prop.MemberType == MemberTypes.Field;
dataTable.Columns.Add(prop.Name, tIsField ? ((FieldInfo)prop).FieldType : ((PropertyInfo)prop).PropertyType);
}
foreach (T item in data)
{
DataRow dr = dataTable.NewRow();
foreach (var field in props)
{
tIsField = field.MemberType == MemberTypes.Field;
object value = tIsField ? ((FieldInfo)field).GetValue(item) : ((PropertyInfo)field).GetValue(item, null);
dr[field.Name] = value;
}
dataTable.Rows.Add(dr);
}
}
return dataTable;

Convert select new to DataTable?

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.

How to work with dataTable?

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);

Categories