I have the same issue as here is LINQ join two DataTables
but my datatables are made on runtime like
DataTable dtTML = (DataTable)JsonConvert.DeserializeObject(Convert.ToString(data.Json.Args[0]["TML"]), (typeof(DataTable)));
the solution that someone gave is fine but I am getting error on datarows2 at
select dtResult.LoadDataRow(new object[]
{
dataRows2.Field<int>("stock") // here is error : does not exist in current context
}
while dataRows1.Field(s) are fine
I can't see what's wrong with this approach :
DataTable dt1 = new DataTable();
dt1.Columns.Add("PK", typeof(int));
dt1.Columns.Add("Data1", typeof(int));
DataTable dt2 = new DataTable();
dt2.Columns.Add("FK", typeof(int));
dt2.Columns.Add("Data2", typeof(int));
dt2.Rows.Add(1, 5000);
dt1.Rows.Add(1, 1000);
var Result = (from r1 in dt1.AsEnumerable()
join r2 in dt2.AsEnumerable()
on r1["PK"] equals r2["FK"]
select new
{
A = r1.Field<int>("Data1"),
B = r2.Field<int>("Data2"),
// choose more columns if any
}).ToList();
You can do whatever you want using it. If you need the result to be a Datatable , just use this method [ ListToDataTable ] to convert List to DataTable:
public static DataTable ListToDataTable<T>(List<T> items)
{
System.ComponentModel.PropertyDescriptorCollection properties =
System.ComponentModel.TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (System.ComponentModel.PropertyDescriptor prop in properties)
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
foreach (T item in items)
{
DataRow row = table.NewRow();
foreach (System.ComponentModel.PropertyDescriptor prop in properties)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
Related
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");
I would like to fill a DataTable object from MySql query, and display with DataGrid. The display part of my code works well (It shows a custom DataTable). Somehow the DataTable fill method won't work for me (i copied it from stackoverflow).
If i fill up DataTable from List with this function is works well
DataTable t = ConvertToDataTable(userlist);
public DataTable ConvertToDataTable<T>(IList<T> data)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
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)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
}
And below the other people's solution what won't work for me. i think table is null.
string searchQuery = "SELECT * FROM USERS";
MySqlCommand command = new MySqlCommand(searchQuery, connection);
MySqlDataAdapter adapter = new MySqlDataAdapter(command);
DataTable table = new DataTable();
adapter.Fill(table);
GridView1.DataSource = table;
this.GridView1.DataBind();
I also attached my MySQL database sample values.
It doesn't fill the DataGrid show no values. Any tips?
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.
I have defined a dataTable Like this
DataTable dtFinal = new DataTable();
dtFinal.Columns.Add("AVNR", typeof(int));
dtFinal.Columns.Add("Substation", typeof(string));
dtFinal.Columns.Add("ColumnTitle", typeof(string));
dtFinal.Columns.Add("S6_NAME", typeof(string));
dtFinal.Columns.Add("Voltage", typeof(string));
dtFinal.Columns.Add("Wert", typeof(decimal));
and I make a join between two tables to have a result set
var results = from table1 in dtTimeListTable.AsEnumerable()
join table2 in readyDataTable.AsEnumerable() on (decimal)table1["Avnr"] equals (int)table2["Avnr"]
select new
{
AVNR = (int)table2["AVNR"],
Substation = (string)table2["Substation"],
ColumnTitle = (string)table2["ColumnTitle"],
S6_NAME = (string)table2["S6_NAME"],
Voltage = (string)table2["Voltage"],
Wert = (decimal)table1["Wert"]
};
to fill datatable up I do the following:
dtFinal.Rows.Add(results.ToArray());
but I'll get a error liek this
input array is longer than the number of columns in this table
both datatable have 6 columns, what could be the problem?
DataRowCollection.Add is a method to add a single DataRow but you are trying to add all rows.
You need a loop:
foreach(var x in query)
dtFinal.Rows.Add(x.AVNR, x.Substation, x.ColumnTitle, x.S6_NAME, x.Voltage, x.Wert);
You could build the object[] for each DataRow also in this way:
var joinedRows = from table1 in dtTimeListTable.AsEnumerable()
join table2 in readyDataTable.AsEnumerable() on (decimal) table1["Avnr"] equals (int) table2["Avnr"]
select new { r1 = table1, r2 = table2 };
foreach (var x in joinedRows)
{
object[] fields =
{
x.r2.Field<int>("AVNR"), x.r2.Field<string>("Substation"), x.r2.Field<string>("ColumnTitle"),
x.r2.Field<int>("S6_NAME"), x.r2.Field<string>("Voltage"), x.r1.Field<decimal>("Wert"),
};
dtFinal.Rows.Add(fields);
}
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);