从Linq To Sql对象获取字段名称

时间:2012-05-03 10:14:50

标签: c# linq

我有一个Linq表达式,我想插入到ADO.NET数据表中。 我想知道查询中字段的名称,以便设置数据表名称。 以下是我的代码示例:

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

我想要做的是设置表名。

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

我试图手动完成,但我相信应该有一个优雅的解决方案。

由于

4 个答案:

答案 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);

答案 1 :(得分:3)

通过使用反射,您可以提取在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);
    }
}

答案 2 :(得分:3)

这可能有点简单;)......

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

答案 3 :(得分: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列field1field2field3
编辑已经投入了时间,所以不妨发布完整的工作示例。

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
            }
        }
    }
}