Преобразовать выбрать новый в DataTable? - PullRequest
6 голосов
/ 30 марта 2012

Я использую .NET 3.5, и мне нужно преобразовать приведенный ниже новый результат в DataTable.Есть ли что-то встроенное для этого или кто-нибудь знает метод, который может это сделать?

var contentList = (from item in this.GetData().Cast<IContent>()
                  select new
                  {
                      Title = item.GetMetaData("Title"),
                      Street = item.GetMetaData("Street"),
                      City = item.GetMetaData("City"),
                      Country = item.GetMetaData("Country")
                  });

Ответы [ 6 ]

7 голосов
/ 30 марта 2012

Легко и просто сделать, чтобы использовать отражение:

var records = (from item in this.GetData().Cast<IContent>()
                           select new
                           {
                               Title = "1",
                               Street = "2",
                               City = "3",
                               Country = "4"
                           });
var firstRecord = records.First();
if (firstRecord == null)
    return;

var infos = firstRecord.GetType().GetProperties();
DataTable table = new DataTable();
foreach (var info in infos) {
    DataColumn column = new DataColumn(info.Name, info.PropertyType);
    table.Columns.Add(column);
}

foreach (var record in records) {
    DataRow row = table.NewRow();
    for (int i = 0; i < table.Columns.Count; i++)
        row[i] = infos[i].GetValue(record);
    table.Rows.Add(row);
}

Код может не работать заранее, но он должен дать вам общее представление. Во-первых, вы получаете propertyInfos от анонимного типа и используете эти метаданные для создания схемы с данными (заполнить столбцы). Затем вы используете эту информацию для получения значений от каждого объекта.

3 голосов
/ 30 марта 2012

Вот одно общее решение без размышлений над свойствами.Используйте метод расширения, как показано ниже:

    public static DataTable ConvertToDataTable<TSource>(this IEnumerable<TSource>
                     records, params Expression<Func<TSource, object>>[] columns)
    {
        var firstRecord = records.First();
        if (firstRecord == null)
            return null;

        DataTable table = new DataTable();

        List<Func<TSource, object>> functions = new List<Func<TSource, object>>();
        foreach (var col in columns)
        {
            DataColumn column = new DataColumn();
            column.Caption = (col.Body as MemberExpression).Member.Name;
            var function = col.Compile();
            column.DataType = function(firstRecord).GetType();
            functions.Add(function);
            table.Columns.Add(column);
        }

        foreach (var record in records)
        {
            DataRow row = table.NewRow();
            int i = 0;
            foreach (var function in functions)
            {
                row[i++] = function((record));
            }
            table.Rows.Add(row);
        }
        return table;
    }

И вызовите его, используя, где параметры будут именем столбца в нужном вам порядке.

var table = records.ConvertToDataTable(
                                        item => item.Title, 
                                        item => item.Street, 
                                        item => item.City
                                      );
0 голосов
/ 14 марта 2014
   public static DataTable ListToDataTable<T>(this IList<T> data)
        {
            DataTable dt = new DataTable();
            PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
            for (int i = 0; i < props.Count; i++)
            {
                PropertyDescriptor prop = props[i];
                dt.Columns.Add(prop.Name, prop.PropertyType);
            }
            object[] values = new object[props.Count];
            foreach (T t in data)
            {
                for (int i = 0; i < values.Length; i++)
                {
                    values[i] = props[i].GetValue(t);
                }
                dt.Rows.Add(values);
            }
            return dt;
        }

После того, как вы сделаете свой выбор нового, вы можете .ToList().ListToDataTable(). Он использует отражение ComponentModel и (теоретически) быстрее, чем System.Reflection.

0 голосов
/ 30 марта 2012

Вы можете преобразовать свой результат списка в данные с помощью функции ниже

   public static DataTable ToDataTable<T>(IEnumerable<T> values)
    {
        DataTable table = new DataTable();

        foreach (T value in values)
        {
            if (table.Columns.Count == 0)
            {
                foreach (var p in value.GetType().GetProperties())
                {
                    table.Columns.Add(p.Name);
                }
            }

            DataRow dr = table.NewRow();
            foreach (var p in value.GetType().GetProperties())
            {
                dr[p.Name] = p.GetValue(value, null) + "";

            }
            table.Rows.Add(dr);
        }

        return table;
    }
0 голосов
/ 30 марта 2012

Попробуйте это:

// Create your datatable.

DataTable dt = new DataTable();
dt.Columns.Add("Title", typeof(string));
dt.Columns.Add("Street", typeof(double));


// get a list of object arrays corresponding
// to the objects listed in the columns
// in the datatable above.
var result = from item in in this.GetData().Cast<IContent>()             
             select dt.LoadDataRow(
                new object[] { Title = item.GetMetaData("Title"),
                              Street = item.GetMetaData("Street"),
                 },
                false);


// the end result will be a set of DataRow objects that have been
// loaded into the DataTable. 

Оригинальная статья для примера кода: Преобразование анонимного типа, сгенерированного LINQ, в тип DataTable

РЕДАКТИРОВАТЬ: Общий псевдокод:

void LinqToDatatable(string[] columns, Type[] datatypes, linqSource)
{
     for loop
     {
       dt.columns.add(columns[i], datatypes[i]);
     }

//Still thinking how to make this generic.. 
var result = from item in in this.GetData().Cast<IContent>()             
             select dt.LoadDataRow(
                new object[] { string[0] = item.GetMetaData[string[0]],
                               string[1] = item.GetMetaData[srring[1]
                 },
                false);


}
0 голосов
/ 30 марта 2012

Существует CopyToDataTable метод расширения , который сделает это за вас.Он живет в System.Data.DataSetExtensions.dll

...