繁体   English   中英

CRecordset :: snapshot在VS2012中不再起作用 - 有什么替代方案?

[英]CRecordset::snapshot doesn't work in VS2012 anymore - what's the alternative?

显然,在VS2012中,不推荐使用SQL_CUR_USE_ODBC。 [更新:似乎游标库已完全从VS2012中删除]。

MFC的CDatabase不再使用它(而它是VS2010和早期版本的MFC的默认设置),而是使用SQL_CUR_USE_DRIVER。

不幸的是,SQL_CUR_USE_DRIVER无法与Jet ODBC驱动程序一起正常工作(我们正在与Access数据库进行交互)。 驱动程序最初声称支持位置操作(但不支持位置更新),但是当尝试实际查询数据库时,所有并发模型都会失败,直到MFC库下降到与数据库的只读交互(这不会发生)为我们飞行)。

问题

  • 这是MS的最新尝试,迫使开发人员放弃基于Jet的数据源并迁移到SQL Express(或类似设备)?
  • 我们应该使用另一种方式通过VS 2012版本的MFC / ODBC与Access数据库进行交互吗?(1)

另见: http//social.msdn.microsoft.com/Forums/kk/vcmfcatl/thread/acd84294-c2b5-4016-b4d9-8953f337f30c


更新:查看各种选项,似乎已从VS2012的ODBC库中删除了游标库。 结合Jet不能正确支持位置更新(2)的事实,它使“快照”模式无法使用。 只要基础表具有主键,它似乎支持“动态集”。 未键控的表与“动态集”模式不兼容(3)。 所以 - 我可以坚持使用VS 2010,或者我可以更改我的表以包含自动编号或类似的东西,以确保pkey可用,因此我可以使用动态集模式用于记录集。


(1)例如,我们是否应该为CRecordset使用不同的开放类型? 我们目前使用CRecordset :: snapshot。 但我从来没有真正理解各种模式快照,动态,动态集。 快速设置“try each”无法获得可访问数据库的可更新接口...
(2)它声称在最初查询时,但随后返回它先前声称支持的所有并发模式的错误
(3)“动态”也出局了,因为Jet根本不支持它(从我的测试中可以看出)。

我找到了似乎有效的解决方案。 我以与VS 2012完全相同的方式覆盖OpenEx,因为我们需要调用AllocConnect的子版本,因为它在父版本中不是虚拟版本。 如上所述,我也覆盖了AllocConnect。 在CDatabase的派生版本中,尝试以下代码:

MyCDatabase.h

BOOL OpenEx(LPCTSTR lpszConnectString, DWORD dwOptions = 0);
void AllocConnect(DWORD dwOptions);

MyCDatabase.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),以便您要求系统不加载游标库。

然后对于记录集,使用动态集CMyRecordset myrs; myrs.Open(CRecordset :: dynaset,...)。

最后,您必须确保您的表具有主键才能使用动态集(键集)。

导出CDatabase并覆盖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进行所有查询。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM