Привет народ. Помогите решить такую траблу.
БД SQL SERVER 2008 DE.
В начала работы данные с сервера записываются в таблицу DataTable, дальше пользователь работает с самим DataTable.
Потом, по запросу, мне нужно сделать Select из самого DataTable, но фишка в том, что структура таблицы:
id int Unchecked
row_guid uniqueidentifier Unchecked
Property geometry Unchecked
и мне нужно сделать Select по полю с типом geometry, если делать SELECT с сервера, то там никаких проблем нет:
SqlParameter newparam1 = new SqlParameter("@g1", SRIDgeom);
newparam1.UdtTypeName = "geometry";
SqlParameter newparam2 = new SqlParameter("@g2", objectGeom);
newparam2.UdtTypeName = "geometry";
String filter = "SELECT @g1.STContains(@g2)";
SqlCommandBuilder cBuild;
SqlDataAdapter dAdapt = new SqlDataAdapter();
dAdapt.SelectCommand = new SqlCommand(filter , sqlCon);
dAdapt.SelectCommand.Parameters.Add(newparam1);
dAdapt.SelectCommand.Parameters.Add(newparam2);
т.е. данное geometry подаю в качестве параметра, а вот как мне сделать Select из DataTable, где
в запросе есть параметры, т.е. запрос типа "SELECT @g1.STContains(@g2)"
Если религия не позволяет linq, тогда только перебирать ручками все строчки и строить фильтр типа 'ID in (...)' — это если фильтр на DataView надо. Если не надо — перебирайте ручками и запихивайте в список.
Re[2]: DataTable.Select() с параметром
От:
Аноним
Дата:
07.05.09 11:14
Оценка:
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Аноним.
S>Linq to dataset спасёт молодого джедая
S>Если религия не позволяет linq, тогда только перебирать ручками все строчки и строить фильтр типа 'ID in (...)' — это если фильтр на DataView надо. Если не надо — перебирайте ручками и запихивайте в список.
Однако спасибо, LINQ прикольная штукенция.
Получилось вот такое:
IEnumerable<DataRow> query = from table1 in table.AsEnumerable()
where (Boolean)table1.Field<SqlGeometry>(geometryPropName).STWithin(objectGeom) == true
select table1;
DataTable newTable = query.CopyToDataTable();
Только вот с динамическими запросами там мутновато немного
Re[2]: DataTable.Select() с параметром
От:
Аноним
Дата:
07.05.09 18:11
Оценка:
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Аноним.
S>Linq to dataset спасёт молодого джедая
S>Если религия не позволяет linq, тогда только перебирать ручками все строчки и строить фильтр типа 'ID in (...)' — это если фильтр на DataView надо. Если не надо — перебирайте ручками и запихивайте в список.
var l = Expression.Lambda<Func<SqlGeometry, bool>>(condition, param);
Console.WriteLine(l);
var q = query.Where(l.Compile());
выдает следующую ошибку при компиляции
The type arguments for method 'System.Linq.Enumerable.Where<TSource>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,int,bool>)'
cannot be inferred from the usage. Try specifying the type arguments explicitly.
у меня работает без проблем, а вот как оформить такой же запрос через Expression, чтобы он вернул IEnumerable<DataRow>, подскажи плз.
Я так и понял что нужно дополнить лямбду доступом к полю, но как это сделать я не пойму
Теперь легко посмотреть какой экспрешн генерит компилятор через рефлектор или дебаггер.
... << RSDN@Home 1.2.0 alpha 4 rev. 1176>>
Re[6]: DataTable.Select() с параметром
От:
Аноним
Дата:
08.05.09 07:35
Оценка:
Здравствуйте, Ziaw, Вы писали:
Z>Здравствуйте, <Аноним>, Вы писали:
А>>Мне нужно строить динамические запросы, поэтому нужны Expression, запрос типа
Z>1. Для многих динамических запросов совсем не обязателен экспрешн, можно просто добавлять условия. Z>
Да, если через AND запросі соединяется тогда этот способ подойдет, а если через OR?
Z>2. Самый простой способ получить експрешн из кода - поручить это компилятору
Z>[c#]
Z>void ExpressionTest(Expression e)
Z>{
Z>}
Z>...
Z>ExpressionTest(row => row.Field<SqlGeometry>(geometryPropName).STWithin(objectGeom));
Z>
Z>Теперь легко посмотреть какой экспрешн генерит компилятор через рефлектор или дебаггер.
что-то не компилится у меня такой вариант
Cannot convert lambda expression to type 'System.Linq.Expressions.Expression' because it is not a delegate type
Re[6]: DataTable.Select() с параметром
От:
Аноним
Дата:
08.05.09 07:42
Оценка:
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Аноним S>1) поменьше оверквота плиз. S>2) Чем не устраивает сценарий приведённый выше:
S>
S>?
А>>Я так и понял что нужно дополнить лямбду доступом к полю, но как это сделать я не пойму
S>Дык у тебя уже есть MethodCall expression. Оберни его во второй (на .Field<T>(columnName)).
Не совсем понял чем мне может помочь первый сценарий, например запрос ColumnA > 1 OR ColumnB < 2
С MethodCall пробую, а примера у тебя нет случайно, а то не получается
Спасибо за помощь!
Здравствуйте, Аноним.
S>>1) поменьше оверквота плиз.
Повторно намекаю на излишнее цитирование
А>Не совсем понял чем мне может помочь первый сценарий, например запрос ColumnA > 1 OR ColumnB < 2
Заведи методы типа
public static Func<DataRow, bool> GetOrCallback(Func<DataRow, bool> a, Func<DataRow, bool> b)
{
return row => a(row) || b(row);
}
По всякому быстрее компиляции лямбд будет.
А>С MethodCall пробую, а примера у тебя нет случайно, а то не получается
См ответ Ziaw.
Кстати, почему CopyToDataTable, а не AsDataView?
Re[8]: DataTable.Select() с параметром
От:
Аноним
Дата:
08.05.09 08:18
Оценка:
Здравствуйте, Sinix, Вы писали: S>Повторно намекаю на излишнее цитирование
Ок
S>По всякому быстрее компиляции лямбд будет.
Хм, ок, буду пробовать.
А>>С MethodCall пробую, а примера у тебя нет случайно, а то не получается S>См ответ Ziaw.
Да, сделал как он говорит получилось аля
Expression<Func<DataRow, System.Data.SqlTypes.SqlBoolean>> expr = row => row.Field<SqlGeometry>(geometryPropName).STWithin(objectGeom);
ExpressionTest(expr);
разбираюсь.
S>Кстати, почему CopyToDataTable, а не AsDataView?
Просто у меня как бы несколько запросов и их результаты я собираю в DataTable, а что есть принципиальная разница?
Здравствуйте, Аноним.
S>>Кстати, почему CopyToDataTable, а не AsDataView? А>Просто у меня как бы несколько запросов и их результаты я собираю в DataTable, а что есть принципиальная разница?
Если вам действительно нужна копия — то всё ок. Иначе огребёте немало граблей с дублированием сущностей и их зависимостей.
Здравствуйте, <Аноним>, Вы писали:
А>что-то не компилится у меня такой вариант А>Cannot convert lambda expression to type 'System.Linq.Expressions.Expression' because it is not a delegate type
Теперь вот гемороюсь как представить Field(value(GsDatabase.Database+<>c__DisplayClass0).geometryPropName)?
Нашел Expression.Field() но не понятно что подавать в первый параметр Expression туда.
Здравствуйте, <Аноним>, Вы писали:
А>Да, так получилось, вот что находится в Expression
А> //{row => row.Field(value(GsDatabase.Database+<>c__DisplayClass0).geometryPropName). А> //STWithin(value(GsDatabase.Database+<>c__DisplayClass0).objectGeom)}
А>Теперь вот гемороюсь как представить Field(value(GsDatabase.Database+<>c__DisplayClass0).geometryPropName)? А>Нашел Expression.Field() но не понятно что подавать в первый параметр Expression туда.
Это сслыка на объект замыкания передаваемый в лямбду, который содержит ссылки на локальные переменные которые используются в ней.
Ziaw, если тебе не сложно, ты не мог бы написать это выражение в виде Expression?
row => row.Field<SqlGeometry>(geometryPropName).STWithin(objectGeom)
А то мне что-то совсем тяжело
Re[10]: DataTable.Select() с параметром
От:
Аноним
Дата:
08.05.09 11:41
Оценка:
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Аноним.
S>>>Кстати, почему CopyToDataTable, а не AsDataView? А>>Просто у меня как бы несколько запросов и их результаты я собираю в DataTable, а что есть принципиальная разница?
S>Если вам действительно нужна копия — то всё ок. Иначе огребёте немало граблей с дублированием сущностей и их зависимостей.
S>Дерзайте дальше
Кстати странно.
var query = sourcetable.AsEnumerable();
Func<DataRow, bool> func1 = r => (bool)r.Field<SqlGeometry>(geometryPropName).STIntersects(objectGeom) == true;
В sourcetable у меня 4 записи, объект пересекает две из них, так вот при query.Where(func1).CopyToDataTable(); в таблице у меня две записи, а в
query = query.Where(func1); в самом query как было 4 так и осталось, т.е. оно не перезаписывает его получается?
Здравствуйте, Аноним
А>В sourcetable у меня 4 записи, объект пересекает две из них, так вот при query.Where(func1).CopyToDataTable(); в таблице у меня две записи, а в А>query = query.Where(func1); в самом query как было 4 так и осталось, т.е. оно не перезаписывает его получается?
4 в таблице или в query после присваивания?
На всякий повторю ещё раз: CopyToDataTable отдаёт копию данных. query.Where(func1) — фильтр по данным. Он никак их не изменяет, просто включает в результат только строки, удовлетворяющие условию. Сам источник при этом не изменяется.