Преобразовать общий список в набор данных в C # - PullRequest
17 голосов
/ 07 августа 2009

У меня есть общий список объектов. Каждый объект имеет 9 строковых свойств. Я хочу превратить этот список в набор данных, который я могу передать в таблицу данных ...... Какой лучший способ сделать это?

Ответы [ 10 ]

64 голосов
/ 15 сентября 2010

Я прошу прощения за то, что поставил ответ на этот вопрос, но я подумал, что это будет самый простой способ просмотреть мой окончательный код. В него включены исправления для обнуляемых типов и нулевых значений: -)

    public static DataSet ToDataSet<T>(this IList<T> list)
    {
        Type elementType = typeof(T);
        DataSet ds = new DataSet();
        DataTable t = new DataTable();
        ds.Tables.Add(t);

        //add a column to table for each public property on T
        foreach (var propInfo in elementType.GetProperties())
        {
            Type ColType = Nullable.GetUnderlyingType(propInfo.PropertyType) ?? propInfo.PropertyType;

            t.Columns.Add(propInfo.Name, ColType);
        }

        //go through each property on T and add each value to the table
        foreach (T item in list)
        {
            DataRow row = t.NewRow();

            foreach (var propInfo in elementType.GetProperties())
            {
                row[propInfo.Name] = propInfo.GetValue(item, null) ?? DBNull.Value;
            }

            t.Rows.Add(row);
        }

        return ds;
    }
13 голосов
/ 07 августа 2009

Вы пытались связать список напрямую с сеткой данных? Если нет, попробуйте сначала, потому что это избавит вас от боли. Если вы уже попробовали это, сообщите нам, что пошло не так, чтобы мы могли лучше проконсультировать вас Привязка данных дает вам различное поведение в зависимости от того, какие интерфейсы реализует ваш объект данных. Например, если ваш объект данных реализует только IEnumerable (например, List), вы получите очень простую одностороннюю привязку, но если он также реализует IBindingList (например, BindingList, DataView), тогда Вы получаете двустороннюю привязку.

12 голосов
/ 27 октября 2009

Существует ошибка с кодом расширения Ли, указанным выше, вам нужно добавить вновь заполненную строку в таблицу t при переборе элементов в списке.

public static DataSet ToDataSet<T>(this IList<T> list) {

Type elementType = typeof(T);
DataSet ds = new DataSet();
DataTable t = new DataTable();
ds.Tables.Add(t);

//add a column to table for each public property on T
foreach(var propInfo in elementType.GetProperties())
{
    t.Columns.Add(propInfo.Name, propInfo.PropertyType);
}

//go through each property on T and add each value to the table
foreach(T item in list)
{
    DataRow row = t.NewRow();
    foreach(var propInfo in elementType.GetProperties())
    {
            row[propInfo.Name] = propInfo.GetValue(item, null);
    }

    //This line was missing:
    t.Rows.Add(row);
}


return ds;

}

5 голосов
/ 07 августа 2009

Вы можете создать метод расширения, чтобы добавить все значения свойств через отражение:

public static DataSet ToDataSet<T>(this IList<T> list)
{
    Type elementType = typeof(T);
    DataSet ds = new DataSet();
    DataTable t = new DataTable();
    ds.Tables.Add(t);

    //add a column to table for each public property on T
    foreach(var propInfo in elementType.GetProperties())
    {
        t.Columns.Add(propInfo.Name, propInfo.PropertyType);
    }

    //go through each property on T and add each value to the table
    foreach(T item in list)
    {
        DataRow row = t.NewRow();
        foreach(var propInfo in elementType.GetProperties())
        {
            row[propInfo.Name] = propInfo.GetValue(item, null);
        }
    }

    return ds;
}
3 голосов
/ 07 августа 2009

Вы можете проверить

http://www.codeproject.com/KB/vb/List2DataSet.aspx

Дает несколько разных подходов.

2 голосов
/ 07 августа 2009

Я сам написал небольшую библиотеку для выполнения этой задачи. Он использует отражение только в первый раз, когда тип объекта должен быть переведен в таблицу данных. Он испускает метод, который выполняет всю работу по переводу типа объекта.

Это самое быстрое решение, которое я знаю (вот почему я его разработал :-)). Вы можете найти его здесь: ModelShredder в GoogleCode

В настоящее время поддерживается только перевод в DataTable. Как вы сформулировали свой вопрос, этого должно быть достаточно. Поддержка DataSets (подумайте о простом обратном ORM) уже разработана, она выйдет в два недостатка, когда я вернусь из отпуска: -)

2 голосов
/ 07 августа 2009

Код грубой силы, чтобы ответить на ваш вопрос:

DataTable dt = new DataTable();

//for each of your properties
dt.Columns.Add("PropertyOne", typeof(string));

foreach(Entity entity in entities)
{
  DataRow row = dt.NewRow();

  //foreach of your properties
  row["PropertyOne"] = entity.PropertyOne;

  dt.Rows.Add(row);
}

DataSet ds = new DataSet();
ds.Tables.Add(dt);
return ds;

Теперь к актуальному вопросу. Зачем тебе это делать? Как упоминалось ранее, вы можете привязать напрямую к списку объектов. Может быть, инструмент отчетности, который принимает только наборы данных?

1 голос
/ 26 февраля 2014

Я немного изменил принятый ответ, обрабатывая типы значений. Я сталкивался с этим при попытке сделать следующее, и поскольку GetProperties () имеет нулевую длину для типов значений, я получал пустой набор данных. Я знаю, что это не тот случай использования ОП, но подумал, что опубликую это изменение на случай, если кто-нибудь еще столкнется с тем же.

Enumerable.Range(1, 10).ToList().ToDataSet();

public static DataSet ToDataSet<T>(this IList<T> list)
{
    var elementType = typeof(T);
    var ds = new DataSet();
    var t = new DataTable();
    ds.Tables.Add(t);

    if (elementType.IsValueType)
    {
        var colType = Nullable.GetUnderlyingType(elementType) ?? elementType;
        t.Columns.Add(elementType.Name, colType);

    } else
    {
        //add a column to table for each public property on T
        foreach (var propInfo in elementType.GetProperties())
        {
            var colType = Nullable.GetUnderlyingType(propInfo.PropertyType) ?? propInfo.PropertyType;
            t.Columns.Add(propInfo.Name, colType);
        }
    }

    //go through each property on T and add each value to the table
    foreach (var item in list)
    {
        var row = t.NewRow();

        if (elementType.IsValueType)
        {
            row[elementType.Name] = item;
        }
        else
        {
            foreach (var propInfo in elementType.GetProperties())
            {
                row[propInfo.Name] = propInfo.GetValue(item, null) ?? DBNull.Value;
            }
        }
        t.Rows.Add(row);
    }

    return ds;
}
0 голосов
/ 01 августа 2017

Я нашел этот код на форуме Microsoft. Это пока один из самых простых способов, который легко понять и использовать. Это сэкономило мне часы, я настроил его как метод расширения без каких-либо изменений в реальном методе. Ниже приведен код. это не требует особых объяснений.

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

1) public static DataSet ToDataSetFromObject (этот объект dsCollection)

2) публичный статический DataSet ToDataSetFromArrayOfObject (этот объект [] arrCollection). Я буду использовать это, например.

// <summary>
// Serialize Object to XML and then read it into a DataSet:
// </summary>
// <param name="arrCollection">Array of object</param>
// <returns>dataset</returns>

public static DataSet ToDataSetFromArrayOfObject( this object[] arrCollection)
{
    DataSet ds = new DataSet();
    try {
        XmlSerializer serializer = new XmlSerializer(arrCollection.GetType);
        System.IO.StringWriter sw = new System.IO.StringWriter();
        serializer.Serialize(sw, dsCollection);
        System.IO.StringReader reader = new System.IO.StringReader(sw.ToString());
        ds.ReadXml(reader);
    } catch (Exception ex) {
        throw (new Exception("Error While Converting Array of Object to Dataset."));
    }
    return ds;
}

Чтобы использовать это расширение в коде

Country[] objArrayCountry = null;
objArrayCountry = ....;// populate your array
if ((objArrayCountry != null)) {
    dataset = objArrayCountry.ToDataSetFromArrayOfObject();
}
0 голосов
/ 07 августа 2009

Один из вариантов - использовать System.ComponenetModel.BindingList, а не список.

Это позволяет использовать его непосредственно в DataGridView. И в отличие от обычного System.Collections.Generic.List обновляет DataGridView при изменениях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...