[Linq] + DataTable
От: Аноним  
Дата: 23.09.11 09:37
Оценка:
Почему такой код выполняется нормально

IEnumerable<DataRow> rows4 =
    from t3 in Data.AsEnumerable().AsQueryable()
    orderby "Column1" descending
    select t3;


А такой — выдаёт ошибку "No property or field 'Column1' exists in type 'DataRow'"

IEnumerable<DataRow> rows5 = Data.AsEnumerable().AsQueryable().OrderBy("Column1");


Как заставить работать второй вариант кода?
Re: [Linq] + DataTable
От: Аноним  
Дата: 23.09.11 09:45
Оценка:
может так

IEnumerable<DataRow> rows5 = Data.AsEnumerable().AsQueryable().t3.OrderBy("Column1");
Re[2]: [Linq] + DataTable
От: Аноним  
Дата: 23.09.11 13:03
Оценка:
Здравствуйте, Аноним, Вы писали:

А>может так


А>IEnumerable<DataRow> rows5 = Data.AsEnumerable().AsQueryable().t3.OrderBy("Column1");


А от куда здесь t3?
Re: [Linq] + DataTable
От: Lloyd Россия  
Дата: 23.09.11 13:25
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Почему такой код выполняется нормально


А>
А>IEnumerable<DataRow> rows4 =
А>    from t3 in Data.AsEnumerable().AsQueryable()
А>    orderby "Column1" descending
А>    select t3;
А>


Скорее всего он работает не так, как вы ожидаете.

А>А такой — выдаёт ошибку "No property or field 'Column1' exists in type 'DataRow'"


А>
А>IEnumerable<DataRow> rows5 = Data.AsEnumerable().AsQueryable().OrderBy("Column1");
А>


А>Как заставить работать второй вариант кода?


OrderBy принимает лямбду, а не строу. Если перевести буквально код выше, то получится:
IEnumerable<DataRow> rows5 = Data.AsEnumerable().AsQueryable().OrderByDescending("Column1");


Но сворее всего вам нужно другое. Вот пример из msdn-а:
var productNames = from products in table.AsEnumerable() select products.Field<string>("ProductName");


Если применить к вашему случаю, то получится что-то типа:
var productNames = from products in Data.AsEnumerable() 
                   orderby products.Field<???>("Column1") descending
                   select products;
Re[2]: [Linq] + DataTable
От: Аноним  
Дата: 23.09.11 13:39
Оценка:
Здравствуйте, Lloyd


string ordering = "Column1";

IQueryble iqueryable;

iqueryable = DynamicQueryable.OrderBy(iqueryable, ordering, new object[0]);



Нужно заставить работать строку DynamicQueryable.OrderBy при iqueryable — выведенном из DataTable.
При iqueryable — выведенном из List<MyObject> — всё OK, а при DataTable — выдаёт ошибку "No property or field 'Column1' exists in type 'DataRow'"

Раз возникает ошибка "No property or field 'Column1' exists in type 'DataRow'", то попробовал создать класс-обёртку для DataRow, который реализует ICustomTypeDescriptor (и ещё класс, реализующий PropertyDescriptor). Но его методы не дёргались.

Тогда я подумал, что Linq не использует ICustomTypeDescriptor и попробовал другую обёртку на основе DynamicObject, но и его методы не дёргались.

Так вот: как бы создать класс-обёртку для этого случая, которая с динамическим набором свойств?

DynamicQueryable.OrderBy(...) — вызывается в сторонней библиотеке (посмотрел через Reflector)
нужно подсунуть ей DataTable или какую-то обёртку, при этом колонки в момент компиляции неизвестны.
Re[3]: [Linq] + DataTable
От: Lloyd Россия  
Дата: 23.09.11 14:13
Оценка:
Здравствуйте, Аноним, Вы писали:

А>DynamicQueryable.OrderBy(...) — вызывается в сторонней библиотеке (посмотрел через Reflector)

А>нужно подсунуть ей DataTable или какую-то обёртку, при этом колонки в момент компиляции неизвестны.

Я не знаю, что такое DynamicQueryable
Re[4]: [Linq] + DataTable
От: Laurel  
Дата: 26.09.11 06:32
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>Я не знаю, что такое DynamicQueryable


Я тоже не знал. Оказалось, это такой велосипед для сборки LINQ запросов в рантайме.
Re[4]: [Linq] + DataTable
От: Аноним  
Дата: 26.09.11 10:58
Оценка:
Здравствуйте, Lloyd

Извиняюсь, я думал, что DynamicQueryable -это стандартная библиотека.

В итоге причину нашёл в недрах DynamicQueryable:

MemberInfo[] members = myObjectType.FindMembers(MemberTypes.Field | MemberTypes.Property, bindingAttr, Type.FilterNameIgnoreCase, (object)memberName);


Если myObjectType — некоторый тип с набором свойств, то этот код возвращает свойство с именем memberName.
Если же myObjectType — DataRow, то у него нет свойства memberName, а есть колонка memberName.

Можно ли как-то подменять DataRow на свой объект со свойствами, созданными по колонкам таблицы.
Т.е. что бы при выполнении этого кода возвращалось описание колонки.

Можно конечно обойти это через выдирание исходников через Reflection + правка и сборка новой библиотеки.

Но может есть другой способ?
Re[5]: [Linq] + DataTable
От: Lloyd Россия  
Дата: 26.09.11 11:00
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Но может есть другой способ?


Можно используя System.Reflection.Emit генерить классы-обертки налету, но это не очень просто.
Re[6]: [Linq] + DataTable
От: Аноним  
Дата: 26.09.11 12:03
Оценка:
Здравствуйте, Lloyd

Помогла статья http://sergeyteplyakov.blogspot.com/2010/12/dynamic-linq.html
Ещё материал есть здастьздесь

Оказалось, что Dynamic LINQ (он же DynamicQueryable) поддерживает создание объектов анонимных классов в Select(str).
Например:

var list2 = Data.AsEnumerable().AsQueryable()
            .Select("new (it["Column1"] AS Column1, it["Column2"] AS Column2)");


Таким образом получаем:

StringBuilder sb = new StringBuilder();
foreach (DataColumn c in this.QueryResultData.DataSource.Columns)
{
    if (sb.Length == 0)
        sb.Append("new (");
    else
        sb.Append(", ");

    sb.Append("it[\"" + c.ColumnName + "\"]");
    sb.Append(" AS ").Append(c.ColumnName);
}
sb.Append(")");

var list = this.QueryResultData.DataSource.AsEnumerable().AsQueryable()
            .Select(sb.ToString());


и передаём list в DynamicQueryable.OrderBy

string ordering = "Column1";

IQueryble iqueryable;

iqueryable = DynamicQueryable.OrderBy(list, ordering, new object[0]);
Re[7]: [Linq] + DataTable
От: Lloyd Россия  
Дата: 26.09.11 12:36
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Lloyd


А>Оказалось, что Dynamic LINQ (он же DynamicQueryable) поддерживает создание объектов анонимных классов в Select(str).


Если честно, мне это не очень интересно.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.