универсальный метод для получения результата linq в datatable для выбора нового с несколькими вариантами выбора - PullRequest
3 голосов
/ 18 июля 2011

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

Это настройка:

public class info
{
    public int id {get;set;}
    public int linked { get; set; }
    public int someNumber { get; set; }
}

        List<info> myInfoList = new List<info>();
        myInfoList.Add(new info { id = 20110102, linked = 1, someNumber = 1 });
        myInfoList.Add(new info { id = 20110103, linked = 2, someNumber = 3 });
        myInfoList.Add(new info { id = 20110104, linked = 3, someNumber = 4 });
        myInfoList.Add(new info { id = 20110105, linked = 4, someNumber = 5 });
        myInfoList.Add(new info { id = 20110106, linked = 5, someNumber = 6 });
        myInfoList.Add(new info { id = 20110107, linked = 1, someNumber = 1 });
        myInfoList.Add(new info { id = 20110108, linked = 2, someNumber = 2 });
        myInfoList.Add(new info { id = 20110109, linked = 3, someNumber = 3 });
        myInfoList.Add(new info { id = 20110110, linked = 4, someNumber = 1 });
        myInfoList.Add(new info { id = 20110111, linked = 1, someNumber = 1 });
        myInfoList.Add(new info { id = 20110112, linked = 1, someNumber = 1 });
        myInfoList.Add(new info { id = 20110113, linked = 2, someNumber = 1 });
        myInfoList.Add(new info { id = 20110114, linked = 2, someNumber = 1 });
        myInfoList.Add(new info { id = 20110115, linked = 3, someNumber = 1 });

        List<info> myInfoList2 = new List<info>();
        myInfoList2.Add(new info { id = 20110102, linked = 1, someNumber = 1 });
        myInfoList2.Add(new info { id = 20110102, linked = 2, someNumber = 3 });
        myInfoList2.Add(new info { id = 20110102, linked = 3, someNumber = 4 });

        List<info> myInfoList3 = new List<info>();
        myInfoList3.Add(new info { id = 20110102, linked = 1, someNumber = 1 });
        myInfoList3.Add(new info { id = 20110103, linked = 2, someNumber = 3 });
        myInfoList3.Add(new info { id = 20110112, linked = 3, someNumber = 4 });


        var outerJoinTest = from x in myInfoList
                            join y in myInfoList2
                            on x.linked equals y.linked
                            into temp
                            from t in temp.DefaultIfEmpty()
                            join z in myInfoList3
                            on x.id equals z.id
                            into temp2
                            from t2 in temp2.DefaultIfEmpty()
                            select new { x, t, t2 };

Я обычноиспользуйте этот метод для преобразования запросов linq в datatable:

        private DataTable LINQToDataTable<T>(IEnumerable<T> varlist)
    {

        DataTable dtReturn = new DataTable();

        PropertyInfo[] columnNames = null;

        if (varlist == null) return dtReturn;

        foreach (T rec in varlist)
        {
            if (columnNames == null)
            {
                columnNames = ((Type)rec.GetType()).GetProperties();
                foreach (PropertyInfo pi in columnNames)
                {
                    Type colType = pi.PropertyType;

                    if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                    {
                        colType = colType.GetGenericArguments()[0];
                    }

                    dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
                }
            }

            DataRow dr = dtReturn.NewRow();

            foreach (PropertyInfo pi in columnNames)
            {
                dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue
                (rec, null);
            }

            dtReturn.Rows.Add(dr);
        }

        return dtReturn;
    }

Но этот метод не работает должным образом с несколькими анонимными выборками.

Я получаю этот результат:

enter image description here

Когда я устанавливаю точку останова в закрытой DataTable LINQToDataTable (IEnumerable varlist) и наведите курсор над параметром rec, я могу увидеть значения, которые я хочу видеть в таблице данных.1019 *

Может кто-нибудь помочь мне изменить метод таким образом, чтобы он выводил результат следующим образом:

enter image description here

1 Ответ

1 голос
/ 19 июля 2011

Примерно так:

private class NestedPropertyInfo
{
    public PropertyInfo Parent { get; set; }
    public PropertyInfo Child { get; set; }
    public string Name { get { return Parent.Name + "_" + Child.Name; } }
}

private DataTable LINQToDataTable<T>(IEnumerable<T> varlist)
{
    DataTable dtReturn = new DataTable();
    NestedPropertyInfo[] columns = null;

    if (varlist == null) return dtReturn;

    foreach (T rec in varlist)
    {
        if (columns == null)
        {
            columns = (
                from p1 in rec.GetType().GetProperties()
                from p2 in p1.PropertyType.GetProperties()
                select new NestedPropertyInfo { Parent = p1, Child = p2 }
                ).ToArray();

            foreach (var column in columns)
            {
                var colType = column.Child.PropertyType;

                if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                {
                    colType = colType.GetGenericArguments()[0];
                }

                dtReturn.Columns.Add(new DataColumn(column.Name, colType));
            }
        }

        DataRow dr = dtReturn.NewRow();

        foreach (var column in columns)
        {
            var parentValue = column.Parent.GetValue(rec, null);
            var childValue = parentValue == null ? null : column.Child.GetValue(parentValue, null);
            dr[column.Name] = childValue ?? DBNull.Value;
        }

        dtReturn.Rows.Add(dr);
    }

    return dtReturn;
}

Кроме того, не имеет отношения к вопросу, но вы действительно должны использовать инициализаторы коллекций:

var myInfoList = new List<info>
{
    new info { id = 20110102, linked = 1, someNumber = 1 },
    new info { id = 20110103, linked = 2, someNumber = 3 },
    new info { id = 20110104, linked = 3, someNumber = 4 },
    // ...
};
...