DataTable.Select() с параметром
От: Аноним  
Дата: 06.05.09 18:37
Оценка:
Привет народ. Помогите решить такую траблу.
БД 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)"

Помогите, плз, очень нужно.
Спасибо.
Re: DataTable.Select() с параметром
От: MozgC США http://nightcoder.livejournal.com
Дата: 06.05.09 18:47
Оценка:
Посмотрите свойство RowFilter класса DataView если мне не изменяет память.
Re: DataTable.Select() с параметром
От: Sinix  
Дата: 07.05.09 01:56
Оценка:
Здравствуйте, Аноним.

Linq to dataset спасёт молодого джедая

Если религия не позволяет 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 надо. Если не надо — перебирайте ручками и запихивайте в список.


Sinix, начал разбираться с LINQ, вот код

IEnumerable<DataRow> query = sourcetable.AsEnumerable();

var param = Expression.Parameter(typeof(SqlGeometry), geometryPropName);
Expression condition = null;
condition = Expression.Call(param, typeof(SqlGeometry).GetMethod("STWithin"),
Expression.Constant(objectGeom));

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.

Подскажи, плз, как это исправить и в чем дело?
Re[3]: DataTable.Select() с параметром
От: Sinix  
Дата: 08.05.09 04:01
Оценка:
А почему не используете typed datasets? И зачем вам expression tree?
var enumerable = table.AsEnumerable;
if (filterByColumnA)
{
  enumerable = enumerable.Where(row=>row.ColumnA==valueForColumnA);
}
if (filterByColumnB)
{
  enumerable = ...
}




Мелочи:

IEnumerable<DataRow> query = from row in table.AsEnumerable()
                             where row.Field<SqlGeometry>(geometryPropName).STWithin(objectGeom)
                             select row;

Запрос работает со строчками, не с табличкой А за лапшекод с == true

DataTable newTable = query.CopyToDataTable();

Это зачем???

var l = Expression.Lambda<Func<SqlGeometry, bool>>(condition, param);
Console.WriteLine(l);
var q = query.Where(l.Compile());

Where требует Func<DataRow, bool>. Так что лямбду придётся дополнить доступом к полю
Re[4]: DataTable.Select() с параметром
От: Аноним  
Дата: 08.05.09 06:45
Оценка:
Здравствуйте, Sinix, Вы писали:

S>А почему не используете typed datasets? И зачем вам expression tree?

S>
S>var enumerable = table.AsEnumerable;
S>if (filterByColumnA)
S>{
S>  enumerable = enumerable.Where(row=>row.ColumnA==valueForColumnA);
S>}
S>if (filterByColumnB)
S>{
S>  enumerable = ...
S>}
S>


S>

S>Мелочи:

S>
S>IEnumerable<DataRow> query = from row in table.AsEnumerable()
S>                             where row.Field<SqlGeometry>(geometryPropName).STWithin(objectGeom)
S>                             select row;
S>

S>Запрос работает со строчками, не с табличкой А за лапшекод с == true

S>
S>DataTable newTable = query.CopyToDataTable();
S>

S>Это зачем???

S>
S>var l = Expression.Lambda<Func<SqlGeometry, bool>>(condition, param);
S>Console.WriteLine(l);
S>var q = query.Where(l.Compile());
S>

S>Where требует Func<DataRow, bool>. Так что лямбду придётся дополнить доступом к полю

Мне нужно строить динамические запросы, поэтому нужны Expression, запрос типа
S>
S>IEnumerable<DataRow> query = from row in table.AsEnumerable()
S>                             where row.Field<SqlGeometry>(geometryPropName).STWithin(objectGeom)
S>                             select row;
S>

у меня работает без проблем, а вот как оформить такой же запрос через Expression, чтобы он вернул IEnumerable<DataRow>, подскажи плз.
Я так и понял что нужно дополнить лямбду доступом к полю, но как это сделать я не пойму
Re[5]: DataTable.Select() с параметром
От: Sinix  
Дата: 08.05.09 07:03
Оценка:
Здравствуйте, Аноним
1) поменьше оверквота плиз.
2) Чем не устраивает сценарий приведённый выше:

var enumerable = table.AsEnumerable;
if (filterByColumnA)
{
  enumerable = enumerable.Where(row=>row.ColumnA==valueForColumnA);
}
if (filterByColumnB)
{
  enumerable = ...
}

?

А>Я так и понял что нужно дополнить лямбду доступом к полю, но как это сделать я не пойму


Дык у тебя уже есть MethodCall expression. Оберни его во второй (на .Field<T>(columnName)).
Re[5]: DataTable.Select() с параметром
От: Ziaw Россия  
Дата: 08.05.09 07:10
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Мне нужно строить динамические запросы, поэтому нужны Expression, запрос типа


1. Для многих динамических запросов совсем не обязателен экспрешн, можно просто добавлять условия.
var query = table.AsEnumerable()
if (objectGeom != null)
  query = query.Where(row => row.Field<SqlGeometry>(geometryPropName).STWithin(objectGeom));
if (!String.IsNullOrEmpty(otherFieldFilter))
  query = query.Where(row => row.Field<string>(otherPropName) == otherFieldFilter;
// etc...

2. Самый простой способ получить експрешн из кода — поручить это компилятору
void ExpressionTest(Expression e)
{
}

...
ExpressionTest(row => row.Field<SqlGeometry>(geometryPropName).STWithin(objectGeom));

Теперь легко посмотреть какой экспрешн генерит компилятор через рефлектор или дебаггер.
... << 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>var enumerable = table.AsEnumerable;
S>if (filterByColumnA)
S>{
S>  enumerable = enumerable.Where(row=>row.ColumnA==valueForColumnA);
S>}
S>if (filterByColumnB)
S>{
S>  enumerable = ...
S>}
S>

S>?

А>>Я так и понял что нужно дополнить лямбду доступом к полю, но как это сделать я не пойму


S>Дык у тебя уже есть MethodCall expression. Оберни его во второй (на .Field<T>(columnName)).


Не совсем понял чем мне может помочь первый сценарий, например запрос ColumnA > 1 OR ColumnB < 2
С MethodCall пробую, а примера у тебя нет случайно, а то не получается
Спасибо за помощь!
Re[7]: DataTable.Select() с параметром
От: Sinix  
Дата: 08.05.09 08:12
Оценка:
Здравствуйте, Аноним.

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, а что есть принципиальная разница?
Re[9]: DataTable.Select() с параметром
От: Sinix  
Дата: 08.05.09 09:10
Оценка:
Здравствуйте, Аноним.

S>>Кстати, почему CopyToDataTable, а не AsDataView?

А>Просто у меня как бы несколько запросов и их результаты я собираю в DataTable, а что есть принципиальная разница?

Если вам действительно нужна копия — то всё ок. Иначе огребёте немало граблей с дублированием сущностей и их зависимостей.

Дерзайте дальше
Re[7]: DataTable.Select() с параметром
От: Ziaw Россия  
Дата: 08.05.09 09:41
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>что-то не компилится у меня такой вариант

А>Cannot convert lambda expression to type 'System.Linq.Expressions.Expression' because it is not a delegate type

а вот так?
        static void ExpressionTest(Expression<Func<DataRow, bool>> e)
        {
        }


        ExpressionTest(row => row.Field<SqlGeometry>(geometryPropName).STWithin(objectGeom));
... << RSDN@Home 1.2.0 alpha 4 rev. 1176>>
Re[8]: DataTable.Select() с параметром
От: Аноним  
Дата: 08.05.09 09:53
Оценка:
Да, так получилось, вот что находится в 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 туда.
Re[9]: DataTable.Select() с параметром
От: Ziaw Россия  
Дата: 08.05.09 10:16
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Да, так получилось, вот что находится в 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 туда.

Это сслыка на объект замыкания передаваемый в лямбду, который содержит ссылки на локальные переменные которые используются в ней.

Его можно тупо заменять на
  Expression.Constant(geometryPropName, typeof(string));
... << RSDN@Home 1.2.0 alpha 4 rev. 1176>>
Re[10]: DataTable.Select() с параметром
От: Аноним  
Дата: 08.05.09 10:23
Оценка:
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;

DataTable resulttable = query.Where(func1).CopyToDataTable();
query = query.Where(func1);

В sourcetable у меня 4 записи, объект пересекает две из них, так вот при query.Where(func1).CopyToDataTable(); в таблице у меня две записи, а в
query = query.Where(func1); в самом query как было 4 так и осталось, т.е. оно не перезаписывает его получается?
Re[11]: DataTable.Select() с параметром
От: Sinix  
Дата: 12.05.09 00:13
Оценка:
Здравствуйте, Аноним

А>В sourcetable у меня 4 записи, объект пересекает две из них, так вот при query.Where(func1).CopyToDataTable(); в таблице у меня две записи, а в

А>query = query.Where(func1); в самом query как было 4 так и осталось, т.е. оно не перезаписывает его получается?

4 в таблице или в query после присваивания?

На всякий повторю ещё раз: CopyToDataTable отдаёт копию данных. query.Where(func1) — фильтр по данным. Он никак их не изменяет, просто включает в результат только строки, удовлетворяющие условию. Сам источник при этом не изменяется.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.