1

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

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

我想做的是设置表名。

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

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

谢谢

4

4 回答 4

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);
于 2012-05-03T11:01:18.190 回答
3

这可能更简单一些;) ...

var fieldNames = (from p in query.GetType().GetProperties() select p.Name).ToArray();
于 2015-04-28T07:51:06.477 回答
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);
    }
}
于 2012-05-03T10:18:05.183 回答
2

因为select new创建了一个匿名类型,所以我知道没有一个简短的优雅解决方案,但你可以做你想做的事。这里的想法是,您将获取查询返回的第一项,并使用匿名类型的类型信息,我们可以反映其属性并填充您的DataTable.

我们可以使用以下方法执行此操作,该方法采用 aDataTableType匿名类型的信息。

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
            }
        }
    }
}
于 2012-05-03T10:31:50.340 回答