2012-05-03 48 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();