CRecordset::snapshot 在 VS2012 中不再起作用 - 还有什么替代方案?
CRecordset::snapshot doesn't work in VS2012 anymore - what's the alternative?
显然,在VS2012中,SQL_CUR_USE_ODBC已被弃用。[更新:游标库似乎已从VS2012中完全删除]。
MFC的C数据库不再使用它(而它是VS2010和早期版本MFC的默认数据库),而是使用SQL_CUR_use_DRIVER。
不幸的是,SQL_CUR_USE_DRIVER无法与Jet ODBC驱动程序正常工作(我们正在与Access数据库交互)。驱动程序最初声称支持位置操作(但不支持位置更新),但当尝试实际查询数据库时,所有并发模型都会失败,直到MFC库降到与数据库的只读交互(这对我们来说是行不通的)。
问题
- 这是MS最近试图迫使开发人员远离基于Jet的数据源并迁移到SQL Express(或类似的)吗
- 我们是否应该使用另一种模式通过VS2012版本的MFC/ODBC与Access数据库进行交互?(1)
另请参阅:http://social.msdn.microsoft.com/Forums/kk/vcmfcatl/thread/acd84294-c2b5-4016-b4d9-8953f337f30c
更新:查看各种选项,光标库似乎已从VS2012的ODBC库中删除。再加上Jet不正确支持位置更新(2),这使得"快照"模式无法使用。只要基础表有主键,它似乎确实支持"dynaset"。无键表与"动态集"模式不兼容(3)。所以-我可以坚持使用VS 2010,或者我可以更改我的表以包括自动编号或类似的内容,以确保pkey可用,这样我就可以对记录集使用dynaset模式。
(1)例如,我们是否应该为CRecordset使用不同的打开类型?我们目前使用CRecordset::snapshot。但我从来没有真正理解过快照、动态、动态集的各种模式。一组快速的"try-each"无法获得访问数据库的可更新接口
(2)它在最初查询时声称支持,但随后返回了以前声称支持的所有并发模式的错误
(3)"动态"也被取消,因为Jet根本不支持它(从我的测试中可以看出)。
我找到了一个似乎有效的解决方案。我以与VS 2012完全相同的方式重写OpenEx,因为我们需要它来调用AllocConnect的子版本,因为它在父版本中不是虚拟的。如前所述,我还覆盖了AllocConnect。在CDatabase的派生版本中,尝试以下代码:
MyC数据库.h
BOOL OpenEx(LPCTSTR lpszConnectString, DWORD dwOptions = 0);
void AllocConnect(DWORD dwOptions);
MyC数据库.cpp
BOOL MyCDatabase::OpenEx(LPCTSTR lpszConnectString, DWORD dwOptions)
{
ENSURE_VALID(this);
ENSURE_ARG(lpszConnectString == NULL || AfxIsValidString(lpszConnectString));
ENSURE_ARG(!(dwOptions & noOdbcDialog && dwOptions & forceOdbcDialog));
// Exclusive access not supported.
ASSERT(!(dwOptions & openExclusive));
m_bUpdatable = !(dwOptions & openReadOnly);
TRY
{
m_strConnect = lpszConnectString;
DATA_BLOB connectBlob;
connectBlob.pbData = (BYTE *)(LPCTSTR)m_strConnect;
connectBlob.cbData = (DWORD)(AtlStrLen(m_strConnect) + 1) * sizeof(TCHAR);
if (CryptProtectData(&connectBlob, NULL, NULL, NULL, NULL, 0, &m_blobConnect))
{
SecureZeroMemory((BYTE *)(LPCTSTR)m_strConnect, m_strConnect.GetLength() * sizeof(TCHAR));
m_strConnect.Empty();
}
// Allocate the HDBC and make connection
AllocConnect(dwOptions);
if(!CDatabase::Connect(dwOptions))
return FALSE;
// Verify support for required functionality and cache info
VerifyConnect();
GetConnectInfo();
}
CATCH_ALL(e)
{
Free();
THROW_LAST();
}
END_CATCH_ALL
return TRUE;
}
void MyCDatabase::AllocConnect(DWORD dwOptions)
{
CDatabase::AllocConnect(dwOptions);
dwOptions = dwOptions | CDatabase::useCursorLib;
// Turn on cursor lib support
if (dwOptions & useCursorLib)
{
::SQLSetConnectAttr(m_hdbc, SQL_ATTR_ODBC_CURSORS, (SQLPOINTER)SQL_CUR_USE_ODBC, 0);
// With cursor library added records immediately in result set
m_bIncRecordCountOnAdd = TRUE;
}
}
请注意,您一开始不想将useCursorLab传递给OpenEx,您需要在AllocConnect的黑客版本中覆盖它。
还要注意,这只是一个黑客,但它似乎是工作。请测试你的所有代码,以确保它按预期工作,但到目前为止,它对我来说还可以。
如果其他人遇到这个问题,答案似乎是:
对于ODBC到Access数据库,请使用CDatabase-mydb进行连接;mydb。OpenEx(..,0),这样您就可以要求系统不要加载光标库。
然后,对于记录集,使用dynaset CMyRecordset myrs;myrs。打开(CRecordset::dynaset,…)。
最后,您必须确保您的表具有主键,以便使用动态集(keyset)。
派生CD数据库并覆盖OpenEx。在派生类CMyDatabase
中,将对AllocConnect
的调用替换为MyAllocConnect
。显然,MyAllocConnect
函数应该使用所需的参数调用SQLSetConnectOption:
// Turn on cursor lib support
if (dwOptions & useCursorLib)
{
AFX_SQL_SYNC(::SQLSetConnectOption(m_hdbc, SQL_ODBC_CURSORS, SQL_CUR_USE_ODBC));
// With cursor library added records immediately in result set
m_bIncRecordCountOnAdd = TRUE;
}
然后对所有查询使用CMyDatabase
类而不是CDatabase
。
- 在 ubuntu3 上C++ goto 定义有什么解决方案吗16.04?
- 使用 Git 处理 C++ Visual Studio 2019 解决方案的外部依赖项源代码管理的最佳方法是什么?
- C++集<T> 什么是最合适的解决方案?
- 使用STL对用户输入数组进行排序的错误有什么解决方案吗?
- 此解决方案中生成更改的方法数量(自上而下)有什么问题?
- gcc中cl/NODEFAULTLIB的替代方案是什么
- 在这种情况下,我们可以使用静态而不是朋友吗,还有其他解决方案是什么
- 模板重载解决方案:当多个模板匹配时会发生什么?
- Windows(Visual Studio)中的-fpermssive标志的替代方案是什么
- 什么是"使用命名空间 std;"的好替代方案?
- 什么是最快的解决方案,用于读/写入哈希映射
- COM 客户端连接 COM 服务器所需的文件是什么(进程外方案)
- SetItemIcon() 在 Mac 10.13 上停止工作,有什么替代方案
- 构建C 插件时的错误,该解决方案是什么
- 当涉及到快速删除时,C++矢量的替代方案是什么
- 我的构建二叉树解决方案有什么问题?
- 从QTcpSocket上的数据流中连续运行复杂算法的最佳Qt线程解决方案是什么
- 为什么C++std::set没有"at"功能,什么是内联替代方案
- 正在(在构造函数中)将其包含一个不良设计的指针传递,如果是的,则解决方案是什么
- Qt 创建者,跟踪:不允许操作.什么是永久解决方案