generic method to get linq result to datatable for select new with multiple selects
I'm trying to get the result of a join query with multiple selects into a dataTable, without selecting every fields separately.
This is the setup:
public class info
{
public int id {get;set;}
public int linked { get; set; }
public int someNumber { get; set; }
}
List<info> myInfoList = new List<info>();
myInfoList.Add(new info { id = 20110102, linked = 1, someNumber = 1 });
myInfoList.Add(new info { id = 20110103, linked = 2, someNumber = 3 });
myInfoList.Add(new info { id = 20110104, linked = 3, someNumber = 4 });
myInfoList.Add(new info { id = 20110105, linked = 4, someNumber = 5 });
myInfoList.Add(new info { id = 20110106, linked = 5, someNumber = 6 });
myInfoList.Add(new info { id = 20110107, linked = 1, someNumber = 1 });
myInfoList.Add(new info { id = 20110108, linked = 2, someNumber = 2 });
myInfoList.Add(new info { id = 20110109, linked = 3, someNumber = 3 });
myInfoList.Add(new info { id = 20110110, linked = 4, someNumber = 1 });
myInfoList.Add(new info { id = 20110111, linked = 1, someNumber = 1 });
myInfoList.Add(new info { id = 20110112, linked = 1, someNumber = 1 });
myInfoList.Add(new info { id = 20110113, linked = 2, someNumber = 1 });
myInfoList.Add(new info { id = 20110114, linked = 2, someNumber = 1 });
myInfoList.Add(new info { id = 20110115, linked = 3, someNumber = 1 });
List<info> myInfoList2 = new List<info>();
myInfoList2.Add(new info { id = 20110102, linked = 1, someNumber = 1 });
myInfoList2.Add(new info { id = 20110102, linked = 2, someNumber = 3 });
myInfoList2.Add(new info { id = 20110102, linked = 3, someNumber = 4 });
List<info> myInfoList3 = new List<info>();
myInfoList3.Add(new info { id = 20110102, linked = 1, someNumber = 1 });
myInfoList3.Add(new info { id = 20110103, linked = 2, someNumber = 3 });
myInfoList3.Add(new info { id = 20110112, linked = 3, someNumber = 4 });
var outerJoinTest = from x in myInfoList
join y in myInfoList2
on x.linked equals y.linked
into temp
from t in temp.DefaultIfEmpty()
join z in myInfoList3
on x.id equals z.id
into temp2
from t2 in temp2.DefaultIfEmpty()
select new { x, t, t2 };
I normally use this method to convert linq queries to datatable:
private DataTable LINQToDataTable<T>(IEnumerable<T> varlist)
{
DataTable dtReturn = new DataTable();
PropertyInfo[] columnNames = null;
if (varlist == null) return dtReturn;
foreach (T rec in varlist)
{
if (columnNames == null)
{
columnNames = ((Type)rec.GetType()).GetProperties();
foreach (PropertyInfo pi in columnNames)
{
Type colType = pi.PropertyType;
if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
{
colType = colType.GetGenericArguments()[0];
}
dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
}
}
DataRow dr = dtReturn.NewRow();
foreach (PropertyInfo pi in columnNames)
{
dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue
(rec, null);
}
dtReturn.Rows.Add(dr);
}
return dtReturn;
}
But this method doesn't work properly with multiple anonymous selects.
I get this result:
When i set a break point in the private DataTable LINQToDataTable(IEnumerable varlist) and hover above rec I can see the values I want to see in the datatable.
can someone help me out to change the method in a 开发者_Go百科way that it outputs the result like this:
How about something like this:
private class NestedPropertyInfo
{
public PropertyInfo Parent { get; set; }
public PropertyInfo Child { get; set; }
public string Name { get { return Parent.Name + "_" + Child.Name; } }
}
private DataTable LINQToDataTable<T>(IEnumerable<T> varlist)
{
DataTable dtReturn = new DataTable();
NestedPropertyInfo[] columns = null;
if (varlist == null) return dtReturn;
foreach (T rec in varlist)
{
if (columns == null)
{
columns = (
from p1 in rec.GetType().GetProperties()
from p2 in p1.PropertyType.GetProperties()
select new NestedPropertyInfo { Parent = p1, Child = p2 }
).ToArray();
foreach (var column in columns)
{
var colType = column.Child.PropertyType;
if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
{
colType = colType.GetGenericArguments()[0];
}
dtReturn.Columns.Add(new DataColumn(column.Name, colType));
}
}
DataRow dr = dtReturn.NewRow();
foreach (var column in columns)
{
var parentValue = column.Parent.GetValue(rec, null);
var childValue = parentValue == null ? null : column.Child.GetValue(parentValue, null);
dr[column.Name] = childValue ?? DBNull.Value;
}
dtReturn.Rows.Add(dr);
}
return dtReturn;
}
Also, not related to the question but you should really use collection initializers:
var myInfoList = new List<info>
{
new info { id = 20110102, linked = 1, someNumber = 1 },
new info { id = 20110103, linked = 2, someNumber = 3 },
new info { id = 20110104, linked = 3, someNumber = 4 },
// ...
};
精彩评论