Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Базы данных под .NET > DataTable.Select() + <DBNull> + DataGridView


Автор: Unlocker 7.12.2008, 22:17
И снова проблемы в нашей БД. Куда же без них...
Суть ее в том, что имеется таблица в DataSet, в которой хотелось производить поиск (читай фильтрацию при помощи DataTable.Select() ).
В целевой таблице много полей и, как полагается, часть из них необязательная. Когда источник заполнился при помощи Fill() и пристыковался к DataGridView, все отображается без траблов. А вот когда налагаем фильтр на данную таблицу и отображаем его в DataGridView вылезает ошибка следующего содержания (см. картинку).
http://ipicture.ru/
Код

 private void btnSearch_Click(object sender, EventArgs e)
        {
            StringBuilder baseFilter = new StringBuilder();
            baseFilter.Append("Name LIKE '%"+txtName.Text+"%'");
            if (txtYear.Text != "")
            { baseFilter.Append(" AND Year = " + txtYear.Text); }
            if (chkSearchSources.CheckedIndices.Contains(1))
            {
                StringBuilder bookFilter = new StringBuilder();
                bookFilter.Append(baseFilter.ToString());
                // хочется вставить еще дополнительные поиски
                dgvBooks.DataSource = dsBooks.Books.Select(bookFilter.ToString());
            }
        }

Как исправить данное недоразумение? Что делать со строками, я сообразил - надо заменить свойство DBNull Action с Throw Exception на Empty. А вот что творить с логическими и целочисленными полями пока я ума не приложу.
попутно задам еще один вопрос, чтобы не создавать потом новую тему. Представим ситуацию, что хочется производить полнотекстовый поиск методом LIKE сразу по нескольким полям таблицы. Как надо составить строку-параметр Expression метода DataTable.Select() ?
Как при наличии нескольких поисков делать пересечение (логический AND), объединение (логический OR) нескольких полнотектовых критериев?
Заранее спасибо.

Автор: MasterOfCode 8.12.2008, 08:33
Насчет данной проблемы не подскажу, но могу подсказать как работать с фильтром через DataView:
Код

DataTable dt;
DataView dv
// ...
dv = dt.DefaultView;
string filter;
filter = "[FieldName] like '%SearchText%' and [OtherFieldName] = 'OtherSearchText'";
dv.RowFilter = filter;


Автор: Unlocker 8.12.2008, 09:32
MasterOfCode, спасибо за быстрый ответ.
Попробую, воплотить твои мысли.
Только вопрос по твоему коду
Цитата

filter = "[FieldName] like '%SearchText%' and [OtherFieldName] = 'OtherSearchText'";

По полю [FieldName] осуществляется полнотектовый поиск, ищущий вхождения данной в фразы в поле, а вот по полю [OtherFieldName] осуществляется жесткий поиск по значению (не полнотекстовый) или я что-то не так понял?

Автор: MasterOfCode 8.12.2008, 09:38
Unlocker,  все правильно понял. Это я так для примера привел, используй свои имена и параметрыsmile

Автор: Unlocker 8.12.2008, 09:51
MasterOfCode, свои данные я вставлю - это не проблема.
меня интересует возможность объединить в одном запросе (фильтре) нескольких полнотекстовых поисков. Или если нельзя напрямую сделать этого, то, например, найти пересечение двух или более результирующих полнотекстовые поиски множеств.

Автор: okaton 11.12.2008, 21:59
Я сейчас пользуюсь таким поиском, может неказистый, но работает smile
Посмотрите, может что-то подойдет.

Код

        string research = null; //переменная нужна, для продолжения поиска
        private void toolStripButton5_Click(object sender, EventArgs e)//Инициализация поиска данных
        {
            if (toolStripTextBox1.Text.Trim() != "") //если в поле пусто или пробелы поиск не выполнять
            {
                search = true;
                this.dataGridView1.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.RowHeaderSelect;

                if (toolStripTextBox1.Text == research) //если текст в строке поиска совпадает, продолжение поиска
                {
                    column_search++; // увеличение индекса колонки для поиска следующего совпадения
                    Search();
                }
                else // если нет, поиск начинается с 0 ячейки
                {
                    rows_search = 0;  //Для первого захода в цикл
                    column_search = 1;//Для первого захода в цикл
                    research = Search();
                    search = false;
                }
                
                toolStripLabel1.Visible = true;
                toolStripButton6.Visible = true;
                toolStripButton5.Text = "Да";
                this.toolStripButton5.Image = global::Set1DataWork.Properties.Resources.SearchY;
            }
        }
        
        int rows_search; //индекс строки в поисковике
        int column_search; //индекс колонки в поисковике
        public string Search()//Поисковик, функция
        {
            string subsearch = toolStripTextBox1.Text.Trim();//переменная для поиска             

            for (int r = rows_search; r < dataGridView1.Rows.Count; r++)
            {
                for (int c = column_search; c < dataGridView1.ColumnCount; c++)
                {
                    //Contains() - метод string, для неточного сравнения 
                    //ToLower() -  метод string, преобразует строку к нижнему регистру, чтобы сравнение было отимальным                    
                    if (Convert.ToString(dataGridView1.Rows[r].Cells[c].Value).ToLower().Contains(subsearch.ToLower()))
                    {
                        dataGridView1.CurrentCell = dataGridView1.Rows[r].Cells[c];
                        rows_search = r;
                        column_search = c;
                        return subsearch;//возвращается, если значение найдено                        
                    }                     
                }
                column_search = 1;
            }

            rows_search = 0;
            column_search = 1;
            Search();
            return "Превед!";//Нужен для функции типа string, программа до этого кода не доходит 
        }       

Автор: Unlocker 11.12.2008, 22:26
Не совсем понял алгоритм твоего поиска. Какая цель перебора по всем полям всех записей?
Реальная бизнес-логика требует совпадения лишь в определенных полях. Имеет смысл организовывать полнотекстовые поиски по полям, возвращая массивы записей для поиска по каждому полю, а для результирующего представления делать пересечение или объединение полученных массивов.
Идея твоя неплоха, но мне кажется, что в реальном приложении простой перебор всех ячеек не принесет желаемого и однозначного результата.

Автор: okaton 11.12.2008, 23:01
 smile видимо в этой теме я лишний, программирование - хобби, а о бизнес проектах я "только" в книжках читал. Звиняйте если что smile 

Автор: Unlocker 11.12.2008, 23:47
okaton, не горячись. просто я прошу дать комментарии к алгоритму. как он работает и для каких условий работы предназначен. надо сопоставлять алгоритм с поставленной задачей, чтобы осознать его адекватность. не бойся написать на абзац больше комментариев.

Цитата

Бизнес-логика — в разработке информационных систем — совокупность правил, принципов, зависимостей, поведения объектов предметной области системы. Иначе можно сказать, что Бизнес-логика — это реализация правил и ограничений автоматизируемых операций. Является синонимом термина «Логика предметной области» (Domain Logic).

К бизнес-логике относятся, к примеру, формулы расчета ежемесячных выплат по ссудам (в финансовой индустрии), автоматизированная отсылка е-мейла руководителю проекта по окончанию выполнения частей задания всеми подчиненными (в системах управления проектами), отказ от отеля при отмене рейса авиакомпанией (в туристическом бизнесе) и т. д.

Источник Википедия.

PS: если слово ни о чем тебе не говорит, найди его смысловое толкование - может, оно не такое страшное, как покажется сперва.  smile  smile 

Автор: okaton 12.12.2008, 00:50
 smile Я не горячусь, я плачу. Ты меня неправильно понял, в моих словах не было переносного смысла. 

Про логику своего кода могу сказать следующее: на объекте стоят в/м комплектами они разные (в смысле комплекты, да к тому же категорированные). Допустим мышка в аварийном состоянии, здесь все просто ищем серийник мышки по (так сказать) базе. А теперь другой вариант у нас есть номер "чего-то" и нужно провести профилактику, я не знаю что искать и тем более, где. И тут спасает поиск по всем объектам, самое плохое что номеров у спец. изделий может быть несколько и некоторые из них почему-то (!) пересекаются.  Других вариантов поиска я не вижу.

А по поводу твоей задачи. Повторюсь программирование - хобби. В силу своих ограниченных знаний  smile 
Цитата

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

ИМХО: Так в чем проблема воспользоваться кодом выше, ограничить поиск ширины и глубины для необходимого поля, вместо подсвечиваемой ячейки поставить "накопитель" массива или коллекции и полученный результат вывести в удобоваримом виде (можно даже в отдельной форме наверняка) согласно relation; в крайнем случае новый datatable и relation. 
Все дело в быстроте подсчета, может быть фильтрами и быстрее (у меня так и не получилось ими воспользоваться), но в их основе же лежит нечто похожее, если это не низкоуровневое программирование (что имеет смысл). 

З.Ы. алгоритм универсальный, наверняка его можно упростить еще лучше (чем проще тем быстрее). По алгоритму происходит вход, перебор (здесь можно указать чего перебирать, а если ввести дополнительные переменные то можно использовать эту функцию для перебора чего угодно, например диагональю для маньяков, и по синусу для суперманьяков (можно же формулу указать)), далее выход из функции и если не менять значение в поле texbox можно продолжить поиск циклично. Т.е. если достигнут финал все начинается заново. Процесс можно автоматизировать и разнообразить по желанию...

Автор: Unlocker 12.12.2008, 01:09
Теперь все понятно. smile 
у меня кодинг тоже был хобби до определенного момента, пока не начал приносить доход)))
Может и правда, стоит организовать несколько отдельных поисков, запихнуть их переменную таблицу, где по необходимости поработать методом DataTable.Merge()?
В общем, вопрос нетривиальный и требует большого объема экспериментов.

PS. 
Только остается вопрос, как работать с выборкой. Если мы подменим переменной таблицей фильтрованную таблицу из DataSet, то как работать с этой выборкой, как сохранить изменения в БД?
Вопросов пока больше, чем ответов. Надо конопатить всю доступную литературу по ADO.NET 2.0

Автор: okaton 12.12.2008, 13:28
Можно использовать уникальные идентификаторы и через них сохранять

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)