crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

3 страниц V  < 1 2 3 >  
Ответить в данную темуНачать новую тему
> Не удается программно изменять значения модели БД, submitAll возвращает false после вызова setRecord
Rocky
  опции профиля:
сообщение 17.2.2009, 21:31
Сообщение #11


Старейший участник
****

Группа: Участник
Сообщений: 530
Регистрация: 22.12.2008
Из: Санкт-Петербург
Пользователь №: 463

Спасибо сказали: 22 раз(а)




Репутация:   7  


:) Не, критика это хорошо )) Правда если она здравая :)

Цитата
...в частности ведь гораздо проще и быстрее обработать `WHERE id=5`, чем `WHERE id=5 AND...

Абсолютно согласен. Да, и спасибо за замечание насчет двойной выборки данных... Действительно косяк.
Вобщем, поробую добавить 2 столбца. 1 pm с автоинкрементом, а 2-й просто целые числа для сортировки записей таблицы. Но, боюсь, это ничего не изменит... Утром будет видно...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 17.2.2009, 22:02
Сообщение #12


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Цитата(Rocky @ 17.2.2009, 21:31) *
Но, боюсь, это ничего не изменит


Я так и делал и все работало нормально. Но тут надо четко понимать, что количество записей в таблице не должно быть слишком много, иначе кирдык. Например у меня на работе MSSQL сервер, где 50 миллионов записей в каждой из 6 таблиц. Если я буду делать такие update'ы пересортировочные, то бизнес загнется :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Rocky
  опции профиля:
сообщение 17.2.2009, 22:38
Сообщение #13


Старейший участник
****

Группа: Участник
Сообщений: 530
Регистрация: 22.12.2008
Из: Санкт-Петербург
Пользователь №: 463

Спасибо сказали: 22 раз(а)




Репутация:   7  


Цитата
50 миллионов записей

:wacko:
Офигеть.....А как в таких случаях быть? Просто интересно, или там новые записи достаточно в конец добавлять?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Константин
  опции профиля:
сообщение 17.2.2009, 22:48
Сообщение #14


Студент
*

Группа: Участник
Сообщений: 69
Регистрация: 9.2.2009
Пользователь №: 539

Спасибо сказали: 15 раз(а)




Репутация:   1  


а зачем вообще сортировать данные непосредственно в таблице бд? в данном конкретном случае это действительно нужно?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
trdm
  опции профиля:
сообщение 17.2.2009, 22:55
Сообщение #15


Дмитрий Трошин
****

Группа: Участник
Сообщений: 575
Регистрация: 12.1.2008
Пользователь №: 68

Спасибо сказали: 21 раз(а)




Репутация:   6  


Цитата(Rocky @ 17.2.2009, 22:38) *
.....или там новые записи достаточно в конец добавлять?

Кажись понял в чем проблема.
Тебе необходимо поштудировать доки по проектированию ИС.
По теории баз данных.
Тут пара полезных курсов: http://www.intuit.ru/catalog/database/
Начни с этого: http://www.intuit.ru/department/database/dbmdi/
Я нечто подобное в колледже проходил. Несмотря на занудные и порою непонятные названия, эта фигня до сих пор значительно помогает.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Rocky
  опции профиля:
сообщение 17.2.2009, 23:02
Сообщение #16


Старейший участник
****

Группа: Участник
Сообщений: 530
Регистрация: 22.12.2008
Из: Санкт-Петербург
Пользователь №: 463

Спасибо сказали: 22 раз(а)




Репутация:   7  


Хм... Если речь идет о таблице с этими трубами, то нет... Но есть таблицы, например с материалами разными.... Там есть группа, есть подгруппа, а есть сами материалы с разными физическими свойствами. Может быть по-хорошему имеет смысл делать отдельно таблицу групп, таблицы подгрупп, таблицы свойств и связывать их через ключи и соотношения 1:N и пр (помню только примерно, базовый курс в универе тока был давно). Но я делаю так (строки таблицы):
|ГРУППА_1|           |               |
|        |ПОДГРУППА_1|               |
|        |           | свойство_1    |
|        |           | свойство_2    |
|        |           | свойство_3    |
|        |ПОДГРУППА_2|               |
|        |           | свойство_1    |
|        |           | свойство_2    |
|        |           | свойство_3    |
|ГРУППА_2|           |               |
|        |ПОДГРУППА_1|               |
|        |           | свойство_1    |
|        |           | свойство_2    |

.......

И пользователю может понадобиться добавить новое свойство для подгруппы 2 например. Если не делать сорировку, то это добавленное свойство перенесется в самый конец, и будет относится не к подгруппе2, а к подгуппе10, например, что будет полной чушью.


---Добавлено позже---
trdm
:)
спасибо, сейчас посмотрим.

Сообщение отредактировал Rocky - 17.2.2009, 23:13
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
trdm
  опции профиля:
сообщение 18.2.2009, 1:06
Сообщение #17


Дмитрий Трошин
****

Группа: Участник
Сообщений: 575
Регистрация: 12.1.2008
Пользователь №: 68

Спасибо сказали: 21 раз(а)




Репутация:   6  


Цитата(Rocky @ 17.2.2009, 23:02) *
trdm, сейчас посмотрим.


ага, судя по тому, что ты написал тебе надо хорошо поработать с сущностями этих групп, подгрупп.
я таки и не понял, свойства группы являются так-же и свойствами подгрупп, у которых эта группа - владелец. Или нет.
это вопрос надо выяснить очень внимательно.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 18.2.2009, 2:09
Сообщение #18


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Rocky, если у тебя такая вещь:
Цитата(Rocky @ 18.2.2009, 2:02) *
Там есть группа, есть подгруппа, а есть сами материалы с разными физическими свойствами.
то лучше всетаки замарочится изучением SQL/СУБД, хранить это в памяти ты можешь сегодня, но завтра уже не сможешь.
Цитата(Rocky @ 18.2.2009, 1:38) *
Просто интересно, или там новые записи достаточно в конец добавлять?
всегда в БД ПРОСТО ДОБАВЛЯЮТ записи, а место положение записи в таблицы значения не имеет, значение имеет результат выборки, тут место будет определятся запросом.

То что ты пытался сделать - вставить запись в определенное место - есть внутренняя механника СУБД под названием индексация, по конкретному полю (столбцу).
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Константин
  опции профиля:
сообщение 18.2.2009, 14:06
Сообщение #19


Студент
*

Группа: Участник
Сообщений: 69
Регистрация: 9.2.2009
Пользователь №: 539

Спасибо сказали: 15 раз(а)




Репутация:   1  


Цитата
|ГРУППА_1| | |
| |ПОДГРУППА_1| |
| | | свойство_1 |

разделить таблицу на три (группа, подгруппа, свойство) и связать их по foreign keys. такой структуры будет достаточно для линейной вложенности - это простой способ.
для вложенности подгрупп в разные группы; для вложенности групп в группы и подгрупп в группы/подгруппы нужен совсем другой подход с таблицами отношений и ограничений. но кажется, тебе подходит простой вариант.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Rocky
  опции профиля:
сообщение 18.2.2009, 14:27
Сообщение #20


Старейший участник
****

Группа: Участник
Сообщений: 530
Регистрация: 22.12.2008
Из: Санкт-Петербург
Пользователь №: 463

Спасибо сказали: 22 раз(а)




Репутация:   7  


По-поводу двойной выборки. Если убрать select(), то данные во вьюхе не отображаются. Открываю assistant, читаю.
Цитата
void QSqlTableModel::setTable ( const QString & tableName ) [virtual]
Sets the database table on which the model operates to tableName. Does not select data from the table, but fetches its field information.

Так что выборка происходит все-таки один раз.

По-поводу автоинкремента. Добавил 2 поля в таблицу: SortID INTEGER и ID INTEGER PRIMARY KEY AUTOINCREMENT. Результат тот же. SubmitAll после программного изменения данных возвращает false. К тому же опять непонятность: да, при формировании таблицы, колонка ID сама заполняется. А при добавлении новой строки в QTableView - нет. Надо либо вручную, либо программно. Но программно не годится (см. выше) - просто не сохраняются данные и все.


А вообще бред какой-то...

Я не понимаю, почему после выполнения следующего кода, запись, которая идет после nRow не удаляется. Ни из моей программы, ни даже если открыть sqlbrowser и оттуда пытаться удалить.
QSqlRecord oSqlRecord = m_pModel->record();
oSqlRecord.setValue(0, QString("%1").arg(nRow + 1));
m_pModel->insertRecord(nRow, oSqlRecord);


Т.е. если писать потом
const int nRowNum = m_pModel->rowCount();
m_pModel->removeRows(0, nRowNum);
m_pModel->submitAll();


то одна строка остается по-любому... Если писать так
QSqlQuery(QString("DELETE FROM %1").arg(m_pModel->tableName()));
m_pModel->select();

то таблица стирается. причем намного быстрее, чем 1-м способом.

Я не понимаю, почему не работает
m_pModel->setSort(0, Qt::AscendingOrder);

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

Попробовал заполнять как хотел QTableWidget вручную (т.е. уйти от модели вообще) - по скорости получается медленнее.

В общем, после 2-х дневного занятия любовью с этим делом, я написал такой код:
void CDataBrowserDialog::OnAddRowAfter()
{
    QSqlDriver *pDriver = QSqlDatabase::database().driver();
    if (pDriver && pDriver->hasFeature(QSqlDriver::Transactions)) QSqlDatabase::database().transaction();

    //добавляем новый ряд
    QModelIndex oInsertIndex = m_pDataTableView->currentIndex();
    int nRow = oInsertIndex.row() == -1 ? 0 : oInsertIndex.row() + 1;
    m_pModel->insertRow(nRow);
    
    oInsertIndex = m_pModel->index(nRow, 1);
    m_pDataTableView->setCurrentIndex(oInsertIndex);
    m_pDataTableView->edit(oInsertIndex);
    m_bRowNumberWasChanged = true;

    if (pDriver && pDriver->hasFeature(QSqlDriver::Transactions)) QSqlDatabase::database().commit();
}

void CDataBrowserDialog::OnDelRow()
{
    QSqlDriver *pDriver = QSqlDatabase::database().driver();
    if (pDriver && pDriver->hasFeature(QSqlDriver::Transactions)) QSqlDatabase::database().transaction();

    //удаляем выделенный ряд
    const int nRow = m_pDataTableView->currentIndex().row();
    m_roDeletedRows.insert(m_pModel->record(nRow).value(0).toInt());
    m_pModel->removeRow(nRow);
    m_bRowNumberWasChanged = true;

    if (pDriver && pDriver->hasFeature(QSqlDriver::Transactions)) QSqlDatabase::database().commit();
}

void InsertRows(const QSqlRecord& oSqlRecord)
{
    CDataBrowserDialog *pApp = CDataBrowserDialog::GetClassPtr();
    pApp->m_pModel->insertRecord(0, oSqlRecord);
}

void CDataBrowserDialog::submitAll2()
{
    //после закрытия диалога надо перезаполнить все коллекции объектов с обновленной базы данных
    m_bNeedToReReadDataBase = true;
    
    //если не были ни добавлены новые строки, ни удалены старые, то просто делаем так (к счастью это работает).
    if (!m_bRowNumberWasChanged)
    {
        m_pModel->submitAll();
        return;
    }

    //в вектор запихиваем все записи таблицы
    std::vector<QSqlRecord> roSqlRecords;
    const int nRowNum = m_pModel->rowCount();

    //предварительно резервируем память, чтобы не было лишнего перераспределения
    roSqlRecords.reserve(nRowNum);

    //начало транзакции
    QSqlDriver *pDriver = QSqlDatabase::database().driver();
    if (pDriver && pDriver->hasFeature(QSqlDriver::Transactions)) QSqlDatabase::database().transaction();

    //формируем вектор на основе таблицы
    int i = 0, j = 0;
    while (i < nRowNum)
    {
        QSqlRecord oSqlRecord = m_pModel->record(i++);
        if (m_roDeletedRows.find(oSqlRecord.value(0).toInt()) != m_roDeletedRows.end()) continue;

        oSqlRecord.setValue(0, QString("%1").arg(++j));
        roSqlRecords.push_back(oSqlRecord);
    }
    
    //сносим все записи таблицы
    QSqlQuery(QString("DELETE FROM %1").arg(m_pModel->tableName()));
    m_pModel->select();

    //а теперь заново формируем таблицу
    std::for_each(roSqlRecords.rbegin(), roSqlRecords.rend(), InsertRows);

    m_pModel->submitAll();

    //конец транзакции
    if (pDriver && pDriver->hasFeature(QSqlDriver::Transactions)) QSqlDatabase::database().commit();

    m_pDataTableView->resizeColumnsToContents();
    m_pDataTableView->resizeRowsToContents();
    m_roDeletedRows.clear();
    m_bRowNumberWasChanged = false;
}


Работает вобщем-то быстро, но таблицы у меня небольшие. Самое большее 300 записей. Но чесгря мне совсем не нравится такой код... Морального удовольствия я не получил :) Пока пусть работает так… надо программу сдавать уже скоро.. а я пока начну изучение sql :)

Всем спасибо за участие!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

3 страниц V  < 1 2 3 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 29.3.2024, 8:21