Поделиться через


TN045. Поддержка MFC и баз данных для типов Long Varchar и Varbinary

Примечание.

Следующее техническое примечание не было обновлено, поскольку сначала оно было включено в электронную документацию. В результате некоторые процедуры и разделы могут быть устаревшими или неверными. Для получения последних сведений рекомендуется выполнить поиск интересующей темы в алфавитном указателе документации в Интернете.

В этом примечании описывается, как получить и отправить SQL_LONGVARCHAR ODBC и SQL_LONGVARBINARY типы данных с помощью классов баз данных MFC.

Обзор поддержки Long Varchar/Varbinary

OdBC SQL_LONG_VARCHAR и SQL_LONGBINARY типы данных (называемые здесь длинными столбцами данных) могут содержать огромные объемы данных. Существует 3 способа обработки этих данных:

  • Привязать его к объекту CString/CByteArray.

  • Привязать его к объекту CLongBinary.

  • Не привязывайте его вообще и не извлекайте и отправляйте длинное значение данных вручную, независимо от классов базы данных.

Каждый из трех методов имеет преимущества и недостатки.

Длинные столбцы данных не поддерживаются для параметров запроса. Они поддерживаются только для outputColumns.

Привязка столбца длинных данных к CString/CByteArray

Преимущества.

Этот подход прост в понимании, и вы работаете с знакомыми классами. Платформа обеспечивает CFormView поддержку CString для DDX_Text. У вас есть много общих функций строки или коллекции с CString классами и CByteArray вы можете контролировать объем памяти, выделенной локально для хранения значения данных. Платформа поддерживает старую копию данных поля во время Edit или AddNew вызовы функций, а платформа может автоматически обнаруживать изменения данных.

Примечание.

Так как CString он предназначен для работы с символьным данными и CByteArray для работы с двоичными данными, рекомендуется поместить символьные данные (SQL_LONGVARCHAR) CStringв , а двоичные данные (SQL_LONGVARBINARY) в CByteArray.

Функции CString RFX для и CByteArray имеют дополнительный аргумент, который позволяет переопределить размер выделенной памяти по умолчанию для хранения полученного значения столбца данных. Обратите внимание на аргумент nMaxLength в следующих объявлениях функций:

void AFXAPI RFX_Text(CFieldExchange* pFX,
    const char *szName,
    CString& value,
    int nMaxLength = 255,
    int nColumnType =
    SQL_VARCHAR);

void AFXAPI RFX_Binary(CFieldExchange* pFX,
    const char *szName,
    CByteArray& value,
    int nMaxLength = 255);

Если вы извлекаете длинный столбец данных в или CString CByteArray, максимальный возвращаемый объем данных по умолчанию составляет 255 байт. Все, что выходит за рамки этого, игнорируется. В этом случае платформа создает исключение AFX_SQL_ERROR_DATA_TRUNCATED. К счастью, можно явно увеличить nMaxLength до более больших значений до MAXINT.

Примечание.

Значение nMaxLength используется MFC для задания локального буфера SQLBindColumn функции. Это локальный буфер для хранения данных и фактически не влияет на объем данных, возвращаемых драйвером ODBC. RFX_Text и RFX_Binary выполните только один вызов, используя SQLFetch для извлечения данных из серверной базы данных. Каждый драйвер ODBC имеет другое ограничение на объем данных, которые они могут возвращать в одном наборе. Это ограничение может быть гораздо меньше, чем значение, заданное в nMaxLength, в этом случае будет создано исключение AFX_SQL_ERROR_DATA_TRUNCATED . В этих обстоятельствах переключитесь на использование RFX_LongBinary вместо RFX_Text или RFX_Binary таким образом, чтобы все данные можно было получить.

ClassWizard привязывает SQL_LONGVARCHAR к CStringвам или SQL_LONGVARBINARY CByteArray к вам. Если вы хотите выделить более 255 байтов, в которые извлекается длинный столбец данных, можно указать явное значение для nMaxLength.

Если длинный столбец данных привязан к или CString CByteArray, обновление поля выполняется так же, как при привязке к SQL_VARCHAR или SQL_VARBINARY. Во время Editзначения данных кэшируются, а затем сравниваются при Update вызове, чтобы обнаружить изменения значения данных и задать значения "Грязный" и NULL для столбца соответствующим образом.

Привязка столбца длинных данных к CLongBinary

Если ваш длинный столбец данных может содержать больше байтов MAXINT данных, вероятно, следует рассмотреть возможность его извлечения в CLongBinary.

Преимущества.

При этом извлекается весь длинный столбец данных до доступной памяти.

Недостатки.

Данные хранятся в памяти. Этот подход также является запретительно дорогостоящим для очень больших объемов данных. Чтобы убедиться, что поле включено в операцию, необходимо вызвать SetFieldDirty связанный Update элемент данных.

Если вы извлекаете длинные столбцы данных в CLongBinaryобъект, классы базы данных будут проверка общий размер длинного столбца данных, а затем выделить HGLOBAL сегмент памяти достаточно большой для хранения всего значения данных. Затем классы базы данных извлекают все значение данных в выделенный HGLOBALобъект.

Если источник данных не может вернуть ожидаемый размер длинного столбца данных, платформа вызовет исключение AFX_SQL_ERROR_SQL_NO_TOTAL. Если попытка выделить сбой, создается исключение стандартной HGLOBAL памяти.

ClassWizard привязывает SQL_LONGVARCHAR или SQL_LONGVARBINARY к CLongBinary вам. Выберите CLongBinary в качестве типа переменной в диалоговом окне "Добавить переменную члена". КлассWizard добавит вызов DoFieldExchange и добавит RFX_LongBinary общее количество привязанных полей.

Чтобы обновить длинные значения столбцов данных, сначала убедитесь, что выделенный HGLOBAL размер достаточно велик для хранения новых данных путем вызова ::GlobalSize в элементе m_hData элемента CLongBinary. Если он слишком мал, отпустите HGLOBAL и выделите один соответствующий размер. Затем задайте m_dwDataLength , чтобы отразить новый размер.

В противном случае, если m_dwDataLength превышает размер заменяемых данных, можно освободить и перераспределить HGLOBALего или оставить выделенным. Обязательно укажите количество байтов, фактически используемых в m_dwDataLength.

Как выполняется обновление CLongBinary

Не обязательно понимать, как обновляется CLongBinary работа, но это может быть полезно в качестве примера по отправке длинных значений данных в источник данных, если выбрать этот третий метод, описанный ниже.

Примечание.

Чтобы CLongBinary поле было включено в обновление, необходимо явно вызвать SetFieldDirty поле. Если изменить поле, в том числе задать значение NULL, необходимо вызвать SetFieldDirty. Кроме того, необходимо вызвать SetFieldNullвторой параметр false, чтобы пометить поле как значение.

При обновлении CLongBinary поля классы баз данных используют механизм DATA_AT_EXEC ODBC (см. документацию ODBC по SQLSetPosаргументу rgbValue). Когда платформа подготавливает инструкцию insert или update вместо указания HGLOBAL на содержащие данные, адрес CLongBinary столбца задается в качестве значения столбца, а индикатор длины, заданный для SQL_DATA_AT_EXEC. Позже, когда инструкция обновления отправляется источнику данных, SQLExecDirect возвращается SQL_NEED_DATA. Это оповещает платформу о том, что значение param для этого столбца фактически является адресом CLongBinary. Платформа вызывает SQLGetData один раз с небольшим буфером, ожидая, что драйвер возвращает фактическую длину данных. Если драйвер возвращает фактическую длину двоичного большого объекта (BLOB), MFC перераспределяет столько места, сколько необходимо для получения БОЛЬШОго двоичного объекта. Если источник данных возвращает SQL_NO_TOTAL, указывая, что он не может определить размер БОЛЬШОго двоичного объекта, MFC создаст меньшие блоки. Начальный размер по умолчанию составляет 64 КБ, а последующие блоки будут двойными. например, второй будет 128K, третий — 256K и т. д. Исходный размер можно настроить.

Не привязка: извлечение и отправка данных непосредственно из ODBC с помощью SQLGetData

С помощью этого метода можно полностью обойти классы базы данных и самостоятельно справиться с длинным столбцом данных.

Преимущества.

При необходимости можно кэшировать данные на диск или определять динамические объемы получаемых данных.

Недостатки.

Вы не получаете платформу Edit или AddNew поддержку, и вам необходимо самостоятельно написать код для выполнения основных функций (Delete работает, хотя это не операция уровня столбца).

В этом случае длинный столбец данных должен находиться в списке выборок набора записей, но не должен быть привязан к платформе. Один из способов сделать это — предоставить собственную инструкцию SQL через GetDefaultSQL или как аргумент lpszSQL функцииCRecordsetOpen, а не привязать дополнительный столбец к вызову функции RFX_. ДЛЯ ODBC требуется, чтобы несвязанные поля отображались справа от привязанных полей, поэтому добавьте в конец списка выбора несвязанный столбец или столбцы.

Примечание.

Так как длинный столбец данных не привязан к платформе, изменения в нем не будут обрабатываться с CRecordset::Update помощью вызовов. Необходимо создать и отправить необходимые инструкции SQL INSERT и UPDATE самостоятельно.

См. также

Технические примечания по номеру
Технические примечания по категории