- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在研究几个使用 ADO 访问 SQL Server 数据库的 Visual Studio 2015 C++ 项目类型。简单示例对表执行选择、读入行、更新每一行并更新表。
MFC 版本工作正常。 Windows 控制台版本是我在更新记录集中的行时遇到问题的地方。 update()
记录集的方法抛出一个 COM 异常,错误文本为:
L"Item cannot be found in the collection corresponding to the requested name or ordinal."
HRESULT
的
0x800a0cc1
.
_RecordsetPtr m_pRecordSet; // recordset object
HRESULT CDBrecordset::UpdateRow(const COleVariant vPutFields, COleVariant vValues)
{
m_hr = 0;
if (IsOpened()) {
try {
m_hr = m_pRecordSet->Update(vPutFields, vValues);
}
catch (_com_error &e) {
_bstr_t bstrSource(e.Description());
TCHAR *description;
description = bstrSource;
TRACE2(" _com_error CDBrecordset::UpdateRow %s %s\n", e.ErrorMessage(), description);
m_hr = e.Error();
}
}
if (FAILED(m_hr))
TRACE3(" %S(%d): CDBrecordset::UpdateRow() m_hr = 0x%x\n", __FILE__, __LINE__, m_hr);
return m_hr;
}
COleSafeArray
调用此函数对象组合成一个帮助器类,以便更容易地指定要更新的列名和值。
// Create my connection string and specify the target database in it.
// Then connect to SQL Server and get access to the database for the following actions.
CString ConnectionString;
ConnectionString.Format(pConnectionStringTemp, csDatabaseName);
CDBconnector x;
x.Open(_bstr_t(ConnectionString));
// Create a recordset object so that we can pull the table data that we want.
CDBrecordset y(x);
// ....... open and reading of record set deleted.
MyPluOleVariant thing(2);
thing.PushNameValue (SQLVAR_TOTAL, prRec.lTotal);
thing.PushNameValue (SQLVAR_COUNTER, prRec.lCounter);
hr = y.UpdateRow(thing.saFields, thing.saValues);
CComSafeArray
作为模板。
COleSafeArray
是从
tagVARIANT
派生的类这是一个
union
这是
VARIANT
的数据结构.但是在 ATL COM 中,
CComSafeArray
是我用作
CComSafeArray<VARIANT>
的模板这似乎是合理的。
CDBsafeArray
源自
CComSafeArray<VARIANT>
,我在调用
m_pRecordSet->Update()
时收到以下编译错误:
no suitable user-defined conversion from "const CDBsafeArray" to "const _variant_t" exists
_variant_t
似乎是
VARIANT
的包装类并且在
CComSafeArray<VARIANT>
之间似乎没有转换路径和
_variant_t
但是在
COleSafeArray
之间有一个转换路径和
_variant_t
.
m_psa
SAFEARRAY
类的成员类型
VARIANT
这可以编译,但是我在测试应用程序时看到了上面的 COM 异常。使用调试器查看对象,指定要更新的字段的对象似乎是正确的。
SAFEARRAY
将与
_variant_t
一起使用的包装类?
最佳答案
Microsoft 简要概述 VARIANT
和 SAFEARRAY
VARIANT
type 用于创建一个变量,该变量可能包含许多不同类型的值。这样的变量可以在一个点被分配一个整数值,在另一个点被分配一个字符串值。 ADO 使用 VARIANT
使用许多不同的方法,以便从数据库读取或写入数据库的值可以通过标准接口(interface)提供给调用者,而不是试图拥有许多不同的、特定于数据类型的接口(interface)。
Microsoft 指定了 VARIANT
表示为 C/C++ 的类型 struct
其中包含许多字段。此 struct
的两个主要部分是一个字段,其中包含一个值,该值表示存储在 VARIANT
中的当前值的类型。以及 VARIANT
支持的各种值类型的 union .
除了VARIANT
另一个有用的类型是 SAFEARRAY
.一个 SAFEARRAY
是一个数组,它包含数组管理数据、关于数组的数据,例如它包含多少元素、它的维度以及上限和下限(边界数据允许您具有任意索引范围)。VARIANT
的 C/C++ 源代码看起来像下面这样(所有组件 struct
和 union
成员似乎都是匿名的,例如 __VARIANT_NAME_2
是 #defined
是空的):
typedef struct tagVARIANT VARIANT;
struct tagVARIANT
{
union
{
struct __tagVARIANT
{
VARTYPE vt;
WORD wReserved1;
WORD wReserved2;
WORD wReserved3;
union
{
LONGLONG llVal;
LONG lVal;
BYTE bVal;
SHORT iVal;
// ... lots of other fields in the union
} __VARIANT_NAME_2;
DECIMAL decVal;
} __VARIANT_NAME_1;
} ;
VARIANT
键入 COM 对象接口(interface)以提供通过接口(interface)来回传递数据和执行所需的任何类型的数据转换(编码)的能力。
VARIANT
type 支持多种数据类型,其中之一是
SAFEARAY
.所以你可以使用
VARIANT
通过
SAFEARRAY
通过接口(interface)。而不是明确的
SAFEARRAY
接口(interface),您可以改为指定
VARIANT
将识别和处理
VARIANT
的接口(interface)包含
SAFEARRAY
.
VARIANT
键入其中一些是:
VariantInit()
VariantClear()
VariantCopy()
SAFEARRAY
键入其中一些是:
SafeArrayCreate()
SafeArrayCreateEx()
SafeArrayCopyData();
VARIANT
类:MFC、ATL、 native C++
_variant_t
似乎是
VARIANT
的标准 C++ 类包装器.
_RecordsetPtr
类有
Update()
接受
_variant_t
的方法对象看起来像:
inline HRESULT Recordset15::Update ( const _variant_t & Fields, const _variant_t & Values ) {
HRESULT _hr = raw_Update(Fields, Values);
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return _hr;
}
VARIANT
的类。类型是
COleVariant
和
COleSafeArray
.如果我们查看这两个类的声明,我们会看到以下内容:
class COleVariant : public tagVARIANT
{
// Constructors
public:
COleVariant();
COleVariant(const VARIANT& varSrc);
// .. the rest of the class declaration
};
class COleSafeArray : public tagVARIANT
{
//Constructors
public:
COleSafeArray();
COleSafeArray(const SAFEARRAY& saSrc, VARTYPE vtSrc);
// .. the rest of the class declaration
};
CComVariant
和
CComSafeArray
然而
CComSafeArray
是一个 C++ 模板。当您使用
CComSafeArray
声明变量时您指定要包含在底层
SAFEARRAY
中的值的类型结构体。声明如下:
class CComVariant : public tagVARIANT
{
// Constructors
public:
CComVariant() throw()
{
// Make sure that variant data are initialized to 0
memset(this, 0, sizeof(tagVARIANT));
::VariantInit(this);
}
// .. other CComVariant class stuff
};
// wrapper for SAFEARRAY. T is type stored (e.g. BSTR, VARIANT, etc.)
template <typename T, VARTYPE _vartype = _ATL_AutomationType<T>::type>
class CComSafeArray
{
public:
// Constructors
CComSafeArray() throw() : m_psa(NULL)
{
}
// create SAFEARRAY where number of elements = ulCount
explicit CComSafeArray(
_In_ ULONG ulCount,
_In_ LONG lLBound = 0) : m_psa(NULL)
{
// .... other CComSafeArray class declaration/definition
};
class _variant_t : public ::tagVARIANT {
public:
// Constructors
//
_variant_t() throw();
_variant_t(const VARIANT& varSrc) ;
_variant_t(const VARIANT* pSrc) ;
// .. other _variant_t class declarations/definition
};
VARIANT
和
SAFEARRAY
.
VARIANT
一起上课
VARIANT
源自
struct tagVARIANT
这允许所有三个可以跨接口(interface)互换使用。不同之处在于每个人如何处理
SAFEARRAY
. MFC 框架提供
COleSafeArray
源自
struct tagVARIANT
并包裹
SAFEARRAY
图书馆。 ATL 框架提供
CComSafeArray
不是源自
struct tagVARIANT
而是使用组合而不是继承。
_variant_t
类有一组构造函数,它们将接受
VARIANT
或指向
VARIANT
的指针以及接受
VARIANT
的赋值和转换操作符方法或指向
VARIANT
的指针.
_variant_t
VARIANT
的方法与 ATL 合作
CComVariant
类和 MFC
COleVariant
和
COleSafeArray
类,因为这些都派生自
struct tagVARIANT
这是
VARIANT
.然而 ATL
CComSafeArray
模板类不适用于
_variant_t
因为它不是从
struct tagVARIANT
继承的.
_variant_t
可以与 ATL 一起使用
CComVariant
或使用 MFC
COleVariant
和
COleSafeArray
但不能与 ATL 一起使用
CComSafeArray
.这样做会产生编译器错误,例如:
no suitable user-defined conversion from "const ATL::CComSafeArray<VARIANT, (VARTYPE)12U>" to "const _variant_t" exists
CComSafeArray
的最简单解决方法似乎是定义一个派生自
CComSafeArray
的类然后提供一个方法来提供
VARIANT
包装
SAFEARRAY
的对象
CComSafeArray
的对象内部
VARIANT
.
struct CDBsafeArray: public CComSafeArray<VARIANT>
{
int m_size;
HRESULT m_hr;
CDBsafeArray(int nSize = 0) : m_size(nSize), m_hr(0)
{
// if a size of number of elements greater than zero specified then
// create the SafeArray which will start out empty.
if (nSize > 0) m_hr = this->Create(nSize);
}
HRESULT CreateOneDim(int nSize)
{
// remember the size specified and create the SAFEARRAY
m_size = nSize;
m_hr = this->Create(nSize);
return m_hr;
}
// create a VARIANT representation of the SAFEARRAY for those
// functions which require a VARIANT rather than a CComSafeArray<VARIANT>.
// this is to provide a copy in a different format and is not a transfer
// of ownership.
VARIANT CreateVariant() const {
VARIANT m_variant = { 0 }; // the function VariantInit() zeros out so just do it.
m_variant.vt = VT_ARRAY | VT_VARIANT; // indicate we are a SAFEARRAY containing VARIANTs
m_variant.parray = this->m_psa; // provide the address of the SAFEARRAY data structure.
return m_variant; // return the created VARIANT containing a SAFEARRAY.
}
};
_RecordsetPtr
Update()
的方法将被称为:
m_hr = m_pRecordSet->Update(saFields.CreateVariant(), saValues.CreateVariant());
关于c++ - _variant_t、COleVariant、CComVariant 和 VARIANT 以及使用 SAFEARRAY 变体之间的用法差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39309122/
我需要修复 getLineNumberFor 方法,以便如果 lastName 的第一个字符位于 A 和 M 之间,则返回 1;如果它位于 N 和 Z 之间,则返回 2。 在我看来听起来很简单,但我不
您好,感谢您的帮助!我有这个: 0 我必须在每次点击后增加“pinli
Javascript 中是否有一种方法可以在不使用 if 语句的情况下通过 switch case 结构将一个整数与另一个整数进行比较? 例如。 switch(integer) { case
我有一列是“日期”类型的。如何在自定义选项中使用“之间”选项? 最佳答案 请注意,您有2个盒子。 between(在SQL中)包含所有内容,因此将框1设置为:DATE >= startdate,将框2
我有一个表,其中包含年、月和一些数字列 Year Month Total 2011 10 100 2011 11 150 2011 12 100 20
这个问题已经有答案了: Extract a substring between double quotes with regular expression in Java (2 个回答) how to
我有一个带有类别的边栏。正如你在这里看到的:http://kees.een-site-bouwen.nl/ url 中类别的 ID。带有 uri 段(3)当您单击其中一个类别时,例如网页设计。显示了一
这个问题在这里已经有了答案: My regex is matching too much. How do I make it stop? [duplicate] (5 个答案) 关闭 4 年前。 我
我很不会写正则表达式。 我正在尝试获取括号“()”之间的值。像下面这样的东西...... $a = "POLYGON((1 1,2 2,3 3,1 1))"; preg_match_all("/\((
我必须添加一个叠加层 (ImageView),以便它稍微移动到包含布局的左边界的左侧。 执行此操作的最佳方法是什么? 尝试了一些简单的方法,比如将 ImageView 放在布局中并使用负边距 andr
Rx 中是否有一些扩展方法来完成下面的场景? 我有一个开始泵送的值(绿色圆圈)和其他停止泵送的值(簧片圆圈),蓝色圆圈应该是预期值,我不希望这个命令被取消并重新创建(即“TakeUntil”和“Ski
我有一个看起来像这样的数据框(Dataframe X): id number found 1 5225 NA 2 2222 NA 3 3121 NA 我有另一个看起来
所以,我正在尝试制作正则表达式,它将解析存储在对象中的所有全局函数声明,例如,像这样 const a = () => {} 我做了这样的事情: /(?:const|let|var)\s*([A-z0-
我正在尝试从 Intellivision 重新创建 Astro-Smash,我想让桶保持在两个 Angular 之间。我只是想不出在哪里以及如何让这个东西停留在两者之间。 我已经以各种方式交换了函数,
到处检查但找不到答案。 我有这个页面,我使用 INNER JOIN 将两个表连接在一起,获取它们的值并显示它们。我有这个表格,用来获取变量(例如开始日期、结束日期和卡号),这些变量将作为从表中调用值的
我陷入了两个不同的问题/错误之间,无法想出一个合适的解决方案。任何帮助将不胜感激 上下文、FFI 和调用大量 C 函数,并将 C 类型包装在 rust 结构中。 第一个问题是ICE: this pat
我在 MySQL 中有一个用户列表,在订阅时,时间戳是使用 CURRENT_TIMESTAMP 在数据库中设置的。 现在我想从此表中选择订阅日期介于第 X 天和第 Y 天之间的表我尝试了几个查询,但不
我的输入是开始日期和结束日期。我想检查它是在 12 月 1 日到 3 月 31 日之间。(年份可以更改,并且只有在此期间内或之外的日期)。 到目前为止,我还没有找到任何关于 Joda-time 的解决
我正在努力了解线程与 CPU 使用率的关系。有很多关于线程与多处理的讨论(一个很好的概述是 this answer )所以我决定通过在运行 Windows 10、Python 3.4 的 8 CPU
我正在尝试编写 PHP 代码来循环遍历数组以创建 HTML 表格。我一直在尝试做类似的事情: fetchAll(PDO::FETCH_ASSOC); ?>
我是一名优秀的程序员,十分优秀!