"Recordset is read-only" - такая ругань при попытке Insert/Delete строку в БД.
CString CTestSet::GetDefaultConnect()
{
return _T("DSN=DataSourceTest;APP=Microsoft\x00ae Visual Studio .NET;WSID=AAA-5RHDC48GY3I;Trusted_Connection=Yes");
}
Не сочтите за труд черкнуть пару строк...
Горит, помогите плиз!!!!! "Recordset is read-only" - такая ругань при попытке Insert/Delete строку в БД. Подскажите, где искать этот флажок read-only в Recordsete. Каркас проекта создавался Мастером в Visual C++.Net . Подсоединяюсь к SQL серверу
CString CTestSet::GetDefaultConnect()
{
return _T("DSN=DataSourceTest;APP=Microsoft\x00ae Visual Studio .NET;WSID=AAA-5RHDC48GY3I;Trusted_Connection=Yes");
}
Не сочтите за труд черкнуть пару строк...
В операции CRecordSet::Open есть опция доступа CRecordSet::readOnly. Может поможет.
Про опции я знаю, я их не устанавливаю, а по умолчанию должно быть не только для чтения.
С самой базой тоже вроде все нормально, через Server Explorer я могу модифицировать базу, а вот в своей программульке - никак:(
Может, еще что подскажете?...
Спасибо, что откликнулись!
Про опции я знаю, я их не устанавливаю, а по умолчанию должно быть не только для чтения.
С самой базой тоже вроде все нормально, через Server Explorer я могу модифицировать базу, а вот в своей программульке - никак:(
Может, еще что подскажете?...
А какая команда SQL у твоего Recordset'а? Если идет выборка из нескольких таблиц, то в Recordset нельзя будет вставить новую строку или удалить уже существующую.
А какая команда SQL у твоего Recordset'а? Если идет выборка из нескольких таблиц, то в Recordset нельзя будет вставить новую строку или удалить уже существующую.
Выборка самая простая: ("SELECT * FROM PriceList ORDER BY ProductName").
Выборка самая простая: ("SELECT * FROM PriceList ORDER BY ProductName").
Пришли код, с помощью которого ты хочешь внести изменения в Recordset.
Пришли код, с помощью которого ты хочешь внести изменения в Recordset.
void CTest1View::OnRecordAdd()
{
if(m_pSet->CanAppend() == 0)
MessageBox("Можно только просматривать записи", "Ошибка добавления записи");
else
{
m_pSet->MoveFirst();
m_pSet->AddNew();
m_flag=true;
UpdateData(false);
}
}
void CTest1View::OnRecordDelete()
{
if(MessageBox("Вы действительно хотите удалить эту запись?",
"Удаление записи",
MB_OKCANCEL|MB_ICONQUESTION| MB_DEFBUTTON2) == IDOK)
try
{
m_pSet->Delete();
}
catch(CDBException e)
{
AfxMessageBox(e.m_strError);
return;
}
m_pSet->MoveNext();
if(m_pSet->IsEOF()) m_pSet->MoveLast ();
if(m_pSet->IsBOF ()) m_pSet->SetFieldNull(NULL);
UpdateData(false);
}
BOOL CTest1View::OnMove(UINT nIDMoveCommand)
{
if (m_flag)
{
m_flag=false;
UpdateData(true);
if (m_pSet->CanUpdate()) m_pSet->Update();
m_pSet->Requery();
UpdateData(false);
return true;
}
else return CRecordView::OnMove(nIDMoveCommand);
}
Самое интересное, что если я без помощи мастера сама создаю соединение, то могу модифицировать базу. А этот мастер очень хитро как-то подключается, никакого тебе .Open(). Он определяет класс - потомок Recordseta, у которого две функции GetDefaultConnect(), GetDefaultSQL(), с помощью которых видимо и происходит подключение и выборка значений.
class CTest1Set : public CRecordset
{
public:
CTest1Set(CDatabase* pDatabase = NULL);
DECLARE_DYNAMIC(CTest1Set)
overrides
public:
virtual CString GetDefaultConnect(); // Default connection string
virtual CString GetDefaultSQL(); // default SQL for Recordset
virtual void DoFieldExchange(CFieldExchange* pFX); // RFX support
}
Вот как выглядят у меня эти функции:
CString CTest2Set::GetDefaultConnect()
{
return _T("DSN=DataSourceTest;WSID=AAA-5RHDC48GY3I;DATABASE=master;Trusted_Connection=Yes");
}
CString CTest2Set::GetDefaultSQL()
{
return _T("SELECT * FROM PriceList ORDER BY ProductName");
}
Внимание, вопрос: как сделать подключение не только для чтения??????
void CTest1View::OnRecordAdd()
{
if(m_pSet->CanAppend() == 0)
MessageBox("Можно только просматривать записи", "Ошибка добавления записи");
else
{
m_pSet->MoveFirst();
m_pSet->AddNew();
m_flag=true;
UpdateData(false);
}
}
void CTest1View::OnRecordDelete()
{
if(MessageBox("Вы действительно хотите удалить эту запись?",
"Удаление записи",
MB_OKCANCEL|MB_ICONQUESTION| MB_DEFBUTTON2) == IDOK)
try
{
m_pSet->Delete();
}
catch(CDBException e)
{
AfxMessageBox(e.m_strError);
return;
}
m_pSet->MoveNext();
if(m_pSet->IsEOF()) m_pSet->MoveLast ();
if(m_pSet->IsBOF ()) m_pSet->SetFieldNull(NULL);
UpdateData(false);
}
BOOL CTest1View::OnMove(UINT nIDMoveCommand)
{
if (m_flag)
{
m_flag=false;
UpdateData(true);
if (m_pSet->CanUpdate()) m_pSet->Update();
m_pSet->Requery();
UpdateData(false);
return true;
}
else return CRecordView::OnMove(nIDMoveCommand);
}
Самое интересное, что если я без помощи мастера сама создаю соединение, то могу модифицировать базу. А этот мастер очень хитро как-то подключается, никакого тебе .Open(). Он определяет класс - потомок Recordseta, у которого две функции GetDefaultConnect(), GetDefaultSQL(), с помощью которых видимо и происходит подключение и выборка значений.
class CTest1Set : public CRecordset
{
public:
CTest1Set(CDatabase* pDatabase = NULL);
DECLARE_DYNAMIC(CTest1Set)
overrides
public:
virtual CString GetDefaultConnect(); // Default connection string
virtual CString GetDefaultSQL(); // default SQL for Recordset
virtual void DoFieldExchange(CFieldExchange* pFX); // RFX support
}
Вот как выглядят у меня эти функции:
CString CTest2Set::GetDefaultConnect()
{
return _T("DSN=DataSourceTest;WSID=AAA-5RHDC48GY3I;DATABASE=master;Trusted_Connection=Yes");
}
CString CTest2Set::GetDefaultSQL()
{
return _T("SELECT * FROM PriceList ORDER BY ProductName");
}
Внимание, вопрос: как сделать подключение не только для чтения??????
Извини за задержку с ответом. Я думаю, что тебе нужно посмотреть в дебаггере, как твой класс открывает соединение и делате выборку данных. Честно признаюсь, в MFC я не силен. Сам пользуюсь ATL OLE DB Templates. Если проводить параллели, по умолчанию ATL OLE DB открывает набор записи только для чтения. Если нужно вносить дополнения или изменения, это нужно выставлять.