2012-12-13 34 views
6

Tôi có một số danh sách được nhập khác nhau mà tôi muốn tham gia và nhận kết quả động.cách lấy tất cả các cột từ kết quả LINQ bằng cách tham gia

Giả sử list1 là danh sách cơ sở. Danh sách 2 và 3 là danh sách có thêm thông tin. Đôi khi tôi muốn các thông tin và trong chạy khác tôi không cần (một trong số họ).

Nếu tôi cần thêm thông tin, tôi biết cột nào tôi muốn nhận.

public struct DateAndValue1 
{ 
    public uint DBDate { get; set; } 
    public double Value1 { get; set; } 
} 

public struct DateAndValue2 
{ 
    public uint DBDate { get; set; } 
    public double Value1 { get; set; } 
    public bool myBool { get; set; } 
    public int someInt { get; set; } 
} 

List<DateAndValue1> list1,list2; 
List<DateAndValue2> list3; 

bool addList2, addList3; 
list1 = new List<DateAndValue1>(); 
list1.Add(new DateAndValue1 { DBDate = 1, Value1 = 10 }); 
list1.Add(new DateAndValue1 { DBDate = 2, Value1 = 20 }); 
list1.Add(new DateAndValue1 { DBDate = 3, Value1 = 30 }); 
list1.Add(new DateAndValue1 { DBDate = 4, Value1 = 40 }); 
list1.Add(new DateAndValue1 { DBDate = 5, Value1 = 50 }); 
list1.Add(new DateAndValue1 { DBDate = 6, Value1 = 60 }); 

list2 = new List<DateAndValue1>(); 
list2.Add(new DateAndValue1 { DBDate = 1, Value1 = 100 }); 
list2.Add(new DateAndValue1 { DBDate = 1, Value1 = 200 }); 
list2.Add(new DateAndValue1 { DBDate = 3, Value1 = 300 }); 
list2.Add(new DateAndValue1 { DBDate = 4, Value1 = 400 }); 
list2.Add(new DateAndValue1 { DBDate = 5, Value1 = 500 }); 
list2.Add(new DateAndValue1 { DBDate = 5, Value1 = 600 }); 

list3 = new List<DateAndValue2>(); 
list3.Add(new DateAndValue2 { DBDate = 1, Value1 = 1000, myBool = true }); 
list3.Add(new DateAndValue2 { DBDate = 2, Value1 = 2000, myBool = true }); 
list3.Add(new DateAndValue2 { DBDate = 2, Value1 = 3000, myBool = true }); 
list3.Add(new DateAndValue2 { DBDate = 4, Value1 = 4000, myBool = true }); 
list3.Add(new DateAndValue2 { DBDate = 6, Value1 = 5000, myBool = true }); 
list3.Add(new DateAndValue2 { DBDate = 6, Value1 = 6000, myBool = true }); 

giả cả thông tin cho danh sách 1 và 2 là cần thiết:

List<dynamic> result = (from a in list1 
         join b in list2 
         on a.DBDate equals b.DBDate 
         select new { DBDate = a.DBDate, Result_A1 = a.Value1, Result_B1 = b.Value1 }).ToList<dynamic>(); 

thông tin từ danh sách 3 đôi khi cần thiết (bây giờ với sự thật, nó sẽ luôn luôn được bổ sung vào kết quả):

if(true) 
{ 
    result = (from so_far in result 
       join c in list3 
       on so_far.a.DBDate equals c.DBDate 
       select new {so_far, Result_C1 = c.Value1,Result_C2=c.myBool }).ToList<dynamic>(); 
} 

Tính năng này hoạt động nhưng kết quả của a và b được kết hợp trong một cột. Vì tôi sẽ sử dụng khoảng 10 danh sách (cũng với các loại khác nhau) mà có thể hoặc không thể khớp, nó rất khó để biết kết quả cuối cùng và do đó làm cái gì đó như:

result = (from so_far in result 
     join c in list3 
     on so_far.a.DBDate equals c.DBDate 
     select new {DBDate= so_far.DBDate, Result_A1=so_far.Result_A1,Result_B1=so_far.Result_B1 , Result_C1 = c.Value1,Result_C2=c.myBool }).ToList<dynamic>(); 

Làm thế nào tôi có thể tự động nhận được tất cả các kết quả có sẵn trong các cột khác nhau, tốt nhất là bỏ qua DBDDate cho tất cả các danh sách được nối, vì vậy DBDate chỉ trong một cột. Kính trọng,

Matthijs

====================================== ======================

thông tin thêm (code) tôi cố gắng để có được những kết quả có thể đọc được:

public DataTable LINQToDataTable<T>(IEnumerable<T> varlist) 
    { 
      DataTable dtReturn = new DataTable(); 

      PropertyInfo[] columnNames = null; 

      if(varlist == null) 
       return dtReturn; 

      try 
      { 
       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); 
       } 
      } 
      catch 
      { 
       return dtReturn; 
      } 
      return dtReturn; 
    } 

Và cố gắng này :

 private class NestedPropertyInfo 
    { 
     public PropertyInfo Parent { get; set; } 
     public PropertyInfo Child { get; set; } 
     public string Name { get { return Parent.Name + "_" + Child.Name; } } 
    } 

    public DataTable LINQMultipleSelectToDataTable<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; 
    } 

Trả lời

2

Không có cách nào dễ dàng để làm thi S.

Vì bạn đang truyền nó tới dynamic dù sao bạn cũng có thể sử dụng ExpandoObject cùng với một số phương pháp trợ giúp.

Bạn sẽ cần người giúp đỡ sau:

public dynamic GetFlatExpando(object o) 
{ 
    IDictionary<string, object> result = new ExpandoObject(); 

    foreach(var property in o.GetType().GetProperties()) 
    { 
     var value = property.GetValue(o, null); 
     var expando = value as ExpandoObject; 
     if(expando == null) 
      result[property.Name] = value; 
     else 
      expando.CopyInto(result); 
    } 

    return result; 
} 

public static class Extensions 
{ 
    public static void CopyInto(this IDictionary<string, object> source, 
           IDictionary<string, object> target) 
    { 
     foreach(var member in source) 
     { 
      target[member.Key] = member.Value; 
     } 
    } 
} 

Và hơn, chỉ cần sử dụng .Select(GetFlatExpando) trước khi cuộc gọi đến ToList trong tất cả các truy vấn:

List<dynamic> result = (from a in list1 
         join b in list2 
         on a.DBDate equals b.DBDate 
         select new { DBDate = a.DBDate, Result_A1 = a.Value1, 
            Result_B1 = b.Value1 }) 
         .Select(GetFlatExpando) 
         .ToList<dynamic>(); 

if(true) 
{ 
    result = (from so_far in result 
       join c in list3 
       on so_far.DBDate equals c.DBDate 
       select new {so_far, Result_C1 = c.Value1,Result_C2=c.myBool }) 
       .Select(GetFlatExpando) 
       .ToList<dynamic>(); 
} 

Mã này có tác dụng phụ tốt đẹp mà DBDate chỉ tồn tại một lần.

Để thực hiện liên kết với các công việc lưới dữ liệu, bạn cần một phương pháp khuyến nông (đặt nó vào lớp Extensions từ trên cao):

public static DataTable ToDataTable(this IEnumerable<IDictionary<string, object>> source) 
{ 
    var result = new DataTable(); 

    foreach(var rowData in source) 
    { 
     var row = result.NewRow(); 

     if(result.Columns.Count == 0) 
     { 
      foreach(var columnData in rowData) 
      { 
       var column = new DataColumn(columnData.Key, 
              columnData.Value.GetType()) 
       result.Columns.Add(column); 
      } 
     } 

     foreach(var columnData in rowData) 
      row[columnData.Key] = columnData.Value; 
     result.Rows.Add(row); 
    } 

    return result; 
} 

Sử dụng nó như thế này:

var dataTable = result.Cast<IDictionary<string, object>>() 
         .ToDataTable(); 
+0

đứng ;-) – user369122

+0

@ user369122: Vui lòng kiểm tra. –

+0

Xin chào, cảm ơn bạn đã nhanh chóng viết mã!Trong chế độ gỡ lỗi, tôi có thể thấy kết quả chính xác trên mỗi hàng kết quả trong "chế độ xem động", nhưng làm cách nào tôi có thể sử dụng đầu ra này làm nguồn cho chế độ xem dữ liệu. dataGridView1.DataSource = kết quả không hiển thị bất cứ điều gì. – user369122

Các vấn đề liên quan