2012-05-03 50 views
2

我有一個Linq表達式,我想將其插入到ADO.NET數據表中。 我想知道查詢中的字段名稱,以設置數據表名稱。 這裏是我的代碼示例:從Linq To Sql對象獲取字段名稱

var result=from item in context.table 
      select new{ 
       field1=... , 
       field2=... , 
       field3=... 
      }; 

我希望做的是設置表名。

Datatable.Columns.Add("field1"); .. etc 

我試着手動做,但我相信應該有一個優雅的解決方案。

感謝

+2

使用反射。 'Type.GetProperties()' – leppie

+0

你現在命名爲field1,...手動設置它們動態嗎? –

+0

是的賽義德,萊比你有這樣的例子嗎? –

回答

4

通過利用反射可以提取您的匿名類型的LINQ表達式創建的屬性的名稱。

var result = from item in context.table 
    select new { 
     field1 = ... , 
     field2 = ... , 
     field3 = ... }; 

if (result.Any()) 
{ 
    Type t = result.First().GetType(); 
    foreach (PropertyInfo p in t.GetProperties()) 
    { 
     // Get the name of the prperty 
     Console.WriteLine(p.Name); 
    } 
} 
+0

試圖做到這一點,但result.GetType()。GetProperties()的計數似乎爲0. –

+0

@DavidRasuli - 代碼中有點改變我添加ToList查詢和gettting第一個元素的屬性只有通過使用結果[0] .GetType();試一試 –

+2

'var pi =(from p in t.GetProperties()select p).ToList();'那裏有嚴重的無用的LINQ濫用。 – leppie

2

因爲select new創建一個匿名類型,沒有一個短優雅的解決方案,我知道的,但你可以做你想做的。這裏的想法是,您將採取查詢返回的第一個項目,並使用匿名類型的類型信息,我們可以反映它的屬性並填寫您的DataTable

我們可以使用以下方法執行此操作,該方法需要匿名類型的DataTableType信息。

public static void FillColumns(DataTable table, Type anonymousType) { 
    PropertyInfo[] properties = anonymousType.GetProperties(); 

    foreach (PropertyInfo property in properties) { 
     table.Columns.Add(property.Name); 
    } 
} 

再比如說,你可以做這樣的事情

var result = from item in context.Table 
      select new { 
       field1 = item.f1, 
       field2 = item.f2, 
       field3 = item.f3 
      }; 

if (result.Count() != 0) { 
    DataTable table = new DataTable("Table"); 
    FillColumns(table, result.First().GetType()); 
} 

DataTable在這短短的例子將產生3列field1field2,並field3
編輯已投入時間,所以不妨發貼完整的實例。

namespace ConsoleApplication1 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Data; 
    using System.Diagnostics; 
    using System.Linq; 
    using System.Reflection; 

    #region Fake Database 

    internal class DatabaseMock 
    { 
     private DatabaseMock() { 
      // Hides the default public constructor created by the compiler 
      // Uses the factory pattern for creation instead 
     } 

     /// <summary> 
     /// Creates a new instance of a database with three default items 
     /// </summary> 
     public static DatabaseMock Create() { 
      DatabaseMock database = new DatabaseMock(); 

      List<ItemMock> items = new List<ItemMock>(); 
      items.Add(new ItemMock("item1")); 
      items.Add(new ItemMock("item2")); 
      items.Add(new ItemMock("item3")); 

      database.Table = items; 

      return database; 
     } 

     /// <summary> 
     /// Gets the items in the database 
     /// </summary> 
     public IEnumerable<ItemMock> Table { 
      get; 
      private set; 
     } 
    } 

    internal struct ItemMock 
    { 
     /// <summary> 
     /// Initializes a new instance of the ItemMock class 
     /// </summary> 
     public ItemMock(string value) { 
      _value = value; 
     } 

     private string _value; 
     /// <summary> 
     /// Gets the items value 
     /// </summary> 
     public string Value { 
      get { 
       return _value; 
      } 
     } 
    } 

    #endregion 

    static class Program 
    { 
     /// <summary> 
     /// Takes the specified DataTable and anonymous type information, and populates the table with a new DataColumn per anonymous type property 
     /// </summary> 
     public static void FillColumns(DataTable table, Type anonymousType) { 
      PropertyInfo[] properties = anonymousType.GetProperties(); 

      foreach (PropertyInfo property in properties) { 
       table.Columns.Add(property.Name); 
      } 
     } 

     static void Main() { 
      DatabaseMock database = DatabaseMock.Create(); 

      var query = 
       from item in database.Table 
       select new { 
        field1 = item.Value, 
        field2 = item.Value, 
        field3 = item.Value 
       }; 

      if (query.Count() != 0) { 
       DataTable table = new DataTable("Table"); 
       FillColumns(table, query.First().GetType()); 

#if DEBUG 
       foreach (DataColumn column in table.Columns) { 
        Debug.WriteLine(column.ColumnName); 
       } 
#endif 
      } 
     } 
    } 
} 
+0

大衛,這不會回顧正確的名稱,它會檢索原始表(在您的情況下的項目)的名稱,而不是field1,2,3 –

+0

我多次運行示例,它返回field1,field2和field3。除非傳入context.Table的類型信息,否則它不會輸出原始表的名稱,這不是本示例的作用。確保傳入'result.First()。GetType()'而不是'context.Table'的類型信息。 –

+0

可能是我的不好,我會檢查它 –

4

我的建議:

var result=from item in context.table 
      select new{ 
       field1=... , 
       field2=... , 
       field3=... 
      }; 

static IEnumerable<string> GetPropertyNames<T>(IEnumberable<T> lst) 
{ 
    foreach (var pi in typeof(T).GetProperties()) 
    { 
    yield return pi.Name; 
    } 
} 

var propnames = GetPropertyNames(result); 
2

這可能是有點簡單;)...

var fieldNames = (from p in query.GetType().GetProperties() select p.Name).ToArray();