Подтвердить что ты не робот

Преобразование общего списка в набор данных в С#

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

4b9b3361

Ответ 1

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

Ответ 2

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

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

Ответ 3

Существует ошибка с расширением кода Ли выше, вам нужно добавить вновь заполненную строку в таблицу 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;

}

Ответ 4

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

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

Ответ 6

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

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;

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

Ответ 7

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

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

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

Ответ 8

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

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

Ответ 9

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

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

Ответ 10

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

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

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

2) public static 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();
}