Udostępnij przez


TN045: Wsparcie MFC/bazy danych dla długich typów varchar/varbinary

Uwaga / Notatka

Następująca uwaga techniczna nie została zaktualizowana, ponieważ została po raz pierwszy uwzględniona w dokumentacji online. W związku z tym niektóre procedury i tematy mogą być nieaktualne lub nieprawidłowe. Aby uzyskać najnowsze informacje, zaleca się wyszukanie interesującego tematu w indeksie dokumentacji online.

W tej notatce opisano sposób pobierania i wysyłania SQL_LONGVARCHAR ODBC oraz SQL_LONGVARBINARY typów danych przy użyciu klas baz danych MFC.

Omówienie obsługi Long Varchar/Varbinary

Typy danych SQL_LONG_VARCHAR ODBC i SQL_LONGBINARY (nazywane tutaj tak długimi kolumnami danych) mogą przechowywać ogromne ilości danych. Istnieją 3 sposoby obsługi tych danych:

  • Powiąż go z elementem CString/CByteArray.

  • Powiąż go z elementem CLongBinary.

  • Nie powiąż jej w ogóle i pobierz oraz wyślij ręcznie długą wartość danych niezależnie od klas związanych z bazą danych.

Każda z trzech metod ma zalety i wady.

Długie kolumny danych nie są obsługiwane w przypadku parametrów zapytania. Są one obsługiwane tylko w przypadku kolumn wyjściowych.

Wiązanie długiej kolumny danych z CString/CByteArray

Zalety:

To podejście jest proste do zrozumienia i pracujesz ze znanymi klasami. Platforma zapewnia CFormView obsługę CStringDDX_Text. Masz wiele ogólnych funkcji dla ciągów lub kolekcji z klasami CString i CByteArray, a także możesz kontrolować lokalnie przydzieloną pamięć do przechowywania wartości danych. Framework utrzymuje starą kopię danych pól podczas wywołań funkcji Edit lub AddNew, a framework może automatycznie wykrywać zmiany w danych.

Uwaga / Notatka

Ponieważ CString jest przeznaczony do pracy z danymi znakami i CByteArray do pracy z danymi binarnymi, zaleca się umieszczenie danych znaków (SQL_LONGVARCHAR) w CString, oraz danych binarnych (SQL_LONGVARBINARY) do CByteArray.

Funkcje RFX dla CString i CByteArray mają dodatkowy argument, który umożliwia zastąpienie domyślnego rozmiaru przydzielonej pamięci do przechowywania pobranej wartości dla kolumny danych. Zwróć uwagę na argument nMaxLength w następujących deklaracjach funkcji:

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);

W przypadku pobrania długiej kolumny danych do obiektu CString lub CByteArraymaksymalna zwracana ilość danych to domyślnie 255 bajtów. Wszystko poza tym jest ignorowane. W takim przypadku struktura zgłosi wyjątek AFX_SQL_ERROR_DATA_TRUNCATED. Na szczęście można jawnie zwiększyć nMaxLength na większe wartości, maksymalnie MAXINT.

Uwaga / Notatka

Wartość nMaxLength jest używana przez MFC do ustawiania lokalnego buforu SQLBindColumn funkcji. Jest to lokalny bufor do przechowywania danych i w rzeczywistości nie wpływa na ilość danych zwracanych przez sterownik ODBC. RFX_Text i RFX_Binary wykonują tylko jedno wywołanie za pomocą SQLFetch, aby pobrać dane z bazy danych backendowej. Każdy sterownik ODBC ma inne ograniczenie co do ilości danych, które może zwrócić podczas jednego pobrania. Ten limit może być znacznie mniejszy niż wartość ustawiona w nMaxLength, w tym przypadku wyjątek AFX_SQL_ERROR_DATA_TRUNCATED zostanie zgłoszony. W tych okolicznościach przełącz się na używanie RFX_LongBinary zamiast RFX_Text lub RFX_Binary tak, aby wszystkie dane mogły zostać pobrane.

ClassWizard przypisze SQL_LONGVARCHAR do CString, lub SQL_LONGVARBINARY do CByteArray dla Ciebie. Jeśli chcesz przeznaczyć więcej niż 255 bajtów na odzyskiwanie danych z długiej kolumny, możesz określić konkretną wartość dla nMaxLength.

Gdy długa kolumna danych jest powiązana z wartością CString lub CByteArray, aktualizowanie pola działa tak samo, jak w przypadku, gdy jest ona powiązana z SQL_VARCHAR lub SQL_VARBINARY. W trakcie Editoperacji wartość danych jest buforowana i później porównywana, gdy Update jest wywoływana w celu wykrywania zmian w wartości danych i odpowiedniego ustawienia wartości Dirty i Null dla kolumny.

Wiązanie długiej kolumny danych do CLongBinary

Jeśli długa kolumna danych może zawierać więcej bajtów danych MAXINT , prawdopodobnie rozważ pobranie ich do elementu CLongBinary.

Zalety:

Spowoduje to pobranie całej długiej kolumny danych do dostępnej pamięci.

Wady:

Dane są przechowywane w pamięci. Takie podejście jest również zbyt drogie w przypadku bardzo dużych ilości danych. Musisz wywołać funkcję SetFieldDirty dla powiązanego elementu danych, aby upewnić się, że pole jest uwzględnione w operacji Update.

W przypadku pobierania długich kolumn danych do CLongBinaryklasy baz danych będą sprawdzać całkowity rozmiar długiej kolumny danych, a następnie przydzielić HGLOBAL segment pamięci wystarczająco duży, aby pomieścić całą wartość danych. Klasy baz danych wówczas pobierają całą wartość danych do przydzielonego elementu HGLOBAL.

Jeśli źródło danych nie może zwrócić oczekiwanego rozmiaru długiej kolumny danych, struktura zgłosi wyjątek AFX_SQL_ERROR_SQL_NO_TOTAL. Jeśli próba przydzielenia elementu HGLOBAL zakończy się niepowodzeniem, zostanie zgłoszony wyjątek pamięci standardowej.

KlasaWizard będzie wiązać SQL_LONGVARCHAR lub SQL_LONGVARBINARY do CLongBinary. Wybierz CLongBinary jako typ zmiennej w oknie dialogowym Dodawanie zmiennej składowej. ClassWizard doda wywołanie RFX_LongBinary do wywołania DoFieldExchange i zwiększy łączną liczbę powiązanych pól.

Aby zaktualizować długie wartości kolumn danych, najpierw upewnij się, że przydzielona przestrzeń HGLOBAL jest wystarczająco duża, aby pomieścić nowe dane, wywołując funkcję ::GlobalSize dla członka m_hData w CLongBinary. Jeśli jest za mały, zwolnij HGLOBAL i przydziel jeden odpowiedni rozmiar. Następnie ustaw m_dwDataLength , aby odzwierciedlić nowy rozmiar.

W przeciwnym razie, jeśli m_dwDataLength jest większy niż rozmiar danych, które zastępujesz, możesz zwolnić i ponownie przydzielić HGLOBAL, lub pozostawić go przydzielony. Pamiętaj, aby wskazać liczbę bajtów używanych w m_dwDataLength.

Jak działa aktualizowanie obiektu CLongBinary

Nie jest konieczne zrozumienie sposobu działania aktualizacji CLongBinary , ale może być przydatne jako przykład sposobu wysyłania długich wartości danych do źródła danych, jeśli wybierzesz tę trzecią metodę, opisaną poniżej.

Uwaga / Notatka

Aby CLongBinary pole było uwzględnione w aktualizacji, należy jawnie wywołać SetFieldDirty dla tego pola. Jeśli wprowadzisz dowolną zmianę w polu, w tym ustawienie wartości Null, musisz wywołać metodę SetFieldDirty. Należy również wywołać SetFieldNull z drugim parametrem jako FALSE, aby oznaczyć pole jako mające wartość.

Podczas aktualizacji pola CLongBinary, klasy baz danych używają mechanizmu ODBC DATA_AT_EXEC (zobacz w dokumentacji ODBC dotyczącej argumentu SQLSetPos rgbValue). Gdy framework przygotowuje instrukcję wstawiania lub aktualizacji, zamiast wskazywać na HGLOBAL zawierające dane, adresCLongBinary jest ustawiany jako wartość kolumny, a wskaźnik długości ustawiony na SQL_DATA_AT_EXEC. Później, gdy instrukcja aktualizacji zostanie wysłana do źródła danych SQLExecDirect, zwrócona zostanie wartość SQL_NEED_DATA. Informuje to strukturę, że wartość parametru dla tej kolumny jest w rzeczywistości adresem CLongBinary. ** Framework wywołuje SQLGetData raz z małym buforem, oczekując, że sterownik zwróci rzeczywistą długość danych. Jeśli sterownik zwraca rzeczywistą długość binarnego dużego obiektu (BLOB), MFC przydziela na nowo tyle miejsca, ile jest potrzebne do pobrania BLOB. Jeśli źródło danych zwróci SQL_NO_TOTAL, co oznacza, że nie może określić rozmiaru obiektu BLOB, usługa MFC utworzy mniejsze bloki. Domyślny rozmiar początkowy to 64K, a kolejne bloki będą mieć dwukrotnie większy rozmiar; na przykład drugi będzie wynosić 128 000, trzeci to 256 tys. itd. Rozmiar początkowy można skonfigurować.

Niewiążące: pobieranie/wysyłanie danych bezpośrednio z odBC za pomocą funkcji SQLGetData

Dzięki tej metodzie całkowicie pomijasz klasy baz danych i samodzielnie zajmujesz się długą kolumną danych.

Zalety:

W razie potrzeby możesz buforować dane na dysku lub zdecydować dynamicznie, ile danych chcesz pobrać.

Wady:

Nie uzyskujesz obsługi Edit lub AddNew przez framework i musisz samodzielnie napisać kod, aby wykonać podstawowe funkcje (Delete działa jednak, ponieważ nie jest to operacja na poziomie kolumny).

W takim przypadku długa kolumna danych musi znajdować się na liście wyboru zestawu rekordów, ale nie powinna być powiązana ze strukturą. Jednym ze sposobów wykonania tej czynności jest podanie własnej instrukcji SQL jako argumentu lpszSQL funkcji GetDefaultSQL lub za pomocą CRecordset, a nie powiązanie dodatkowej kolumny z wywołaniem funkcji RFX_. ODBC wymaga, aby pola niepowiązane znajdowały się po prawej stronie pól powiązanych, dlatego dodaj niezwiązaną kolumnę lub kolumny na końcu listy wyboru.

Uwaga / Notatka

Ponieważ długa kolumna danych nie jest powiązana ze strukturą, zmiany w niej nie będą obsługiwane za pomocą CRecordset::Update wywołań. Musisz utworzyć i wysłać wymagane instrukcje SQL INSERT i UPDATE samodzielnie.

Zobacz także

Uwagi techniczne według numeru
Uwagi techniczne według kategorii