Teach Yourself Database Programming
with Visual C++ 6 in 21 days
Appendix F
Answers
-
Day 1, "Choosing the Right Database Technology"
-
Day 2, "Tools for Database Development in Visual C++
Developer Studio"
-
Day 3, "Retrieving Data Through Structured Query Language
(SQL)
-
Day 4, "Retrieving SQL Data Through a C++ API"
-
Day 5, "Adding, Modifying, and Deleting Data"
-
Day 6, "Harnessing the Power of Relational Database Servers"
-
Day 7, "Database Design"
-
Day 8, "Utilizing the Capabilities of Database Servers"
-
Day 9, "Understanding COM"
-
Day 10, "Database Client Technologies and the Secrets
of ADO"
-
Day 11, "Multitier Architectures"
-
Day 12, "Using Microsoft Transaction Server to Build
Scalable Applications"
-
Day 13, "Melding Object-Oriented Programming with Relational
Databases"
-
Day 14, "Legacy Database APIs"
-
Chapter 15, "The ODBC API and the MFC ODBC Classes"
-
Day 16, "The Ultimate Database API: OLE DB"
-
Day 17, "Accessing a Data Source with OLE DB"
-
Chapter 18, "Querying a Data Source with OLE DB"
-
Day 20, "Properties, Transactions, and Indexes"
-
Day 21, "OLE DB Error Handling"
- What are the primary benefits of using a record manager (such
as Btrieve) rather than inventing your own database routines?
If you use a record manager (such as Btrieve), you don't have
to build the code for navigation, searching, indexing, and locking
for multiple users.
- What do the desktop databases provide that record managers
do not?
Desktop databases provide data files that contain metadata, so
the data files are self-describing. Record managers do not.
- What are the benefits of using a database technology that
provides open, accessible data stores?
If you use a database technology that provides open, accessible
data stores, your application will live longer. Also, in the future,
you will not be derided by your customers and other developers
for your lack of vision in building an inaccessible database with
your application.
- Which database technologies provide open, accessible data
stores?
The database technologies that provide open, accessible databases
are desktop databases and relational database servers.
- What is the significance of server-side processing of set-based
operations in a client/server architecture?
Server-side processing of set-based operations means less network
traffic and greater scalability of your application.
- The code in Listing 1.1 creates a data file that contains
order information. Write a program that reads the order data from
that file.
The code below opens the data.dat file and reads the date and
product. It then sends the product name to the display.
ifstream is( "data.dat", ios::binary | ios::nocreate );
if( is )
{
is.read( (char *) &dt, sizeof( dt ) );
is.read( (char *) &prod, sizeof( prod ) );
cout << prod.szName << endl;
}
else
{
cout << "ERROR: Cannot open file 'data.dat'." << endl;
}
)
- Decide which database technology would be most appropriate
for the sample application described earlier. Create a list of
capabilities that the database for this application needs to provide.
Justify your decision by comparing the database requirements with
the capabilities of the database technology that you have chosen.
The database for this application needs to work well in a LAN
environment, provide multiple users with simultaneous access to
the data, give good performance so that people don't have to wait
long when placing their orders, and use an open database format
so that the data can be analyzed by managers. Also, of course,
you don't want to spend a long time just building the database.
A desktop database such as Access fills most requirements, except
perhaps in the area of performance. If the number of users (the
sales reps who take the phone calls) is fewer than five or six,
Access's performance will probably be adequate. If the number
of users is more than five or six, a relational database server
is the technology that will fill all the requirements.
- Which editions of Visual C++ enable viewing and editing data
from relational databases inside Visual Studio?
The Visual C++ Professional and Enterprise Editions.
- What is a DSN?
A DSN is a data source name. The term DSN refers to an
ODBC data source created on a computer, which points to some database
and specifies some ODBC driver that can read from and write to
that database.
- What gives a database its value and why?
A database's value is derived from its structure. The better,
the more complete, the more descriptive, the more widely accepted
the structure of a database, the more valuable its data can be.
- What is the fundamental requirement for records in relational
database?
Each record must be unique. There must not be any duplicate records
in a relational database.
- What mechanism is used to relate records in different tables
to one another?
Records in different tables are related to each other through
primary and foreign keys. A record's primary key uniquely identifies
it in the database. That primary key can appear in other tables
to indicate a relationship between that record and the records
in other tables. A primary key that appears in another table is
called a foreign key.
- Open the Orders table in the database project you
created today. Note the foreign keys that appear in the table.
Open the Customers and Products tables and see
primary keys for customers and products. Try to change one of
the foreign key values, such as a customer number, to a number
that doesn't exist as a primary key. What happens? Does the database
help enforce the integrity of the data?
When you try to change one of the foreign key values in the Orders
table, such as a customer number, to a number that does not exist
as a primary key, the database will not accept the change, and
you will get an error message saying that this change would violate
referential integrity rules.
- Open the Orders table in the database project you
created today. Try to change one of the order numbers in the table
by typing in letters for the contents of the field. When you move
the cursor off that record, what happens? Does the database validate
the data type you tried to enter? (You can press Esc to abort
the edit.)
- What is SQL?
SQL is an acronym for Structured Query Language. SQL is
a data manipulation and definition language designed specifically
for relational databases.
- What is an SQL join?
An SQL join is a SELECT statement that produces a resultset
by using data from two or more tables in a relational database.
- What is wrong with this SQL query?
SELECT customers.*
WHERE customers.custnumber = 3
The query is missing the FROM clause. It needs to say
the following:
SELECT customers.*
FROM customers
WHERE customers.custnumber = 3
- What is an aggregate function?
An aggregate function operates on multiple records and returns
a single value.
- What does a cursor make possible?
A cursor defines a position in a resultset and makes it possible
to move through the resultset one record at a time.
- Discover what happens when you add a table name to the FROM
clause without mentioning that table in the WHERE class
of an SQL SELECT statement, like this:
SELECT customers.*
FROM customer, orders
WHERE customers.custnumber = 3
The resultset contains a Cartesian product of the two tables,
meaning that if one table has 3 records and the other has 5 records,
the resultset will contain 15 records. In the case of the database
you've been using today, the resultset will contain 4 records.
- Add a join to the SQL query shown in Figure 3.22 to retrieve
the name of the customer who placed the most recent order.
You must nest the subquery that finds the last order date in the
subquery that finds the customer number, which subquery you must
nest in the query to obtain the customer information.
SELECT 'Customers'.*
FROM 'Customers'
WHERE custnumber IN
(
SELECT 'Orders'.customernumber
FROM 'Orders'
WHERE orderdate =
(
SELECT MAX(orderdate)
FROM Orders
)
)
- What does a database API do?
A database API translates between the type system of C++ and the
type system of the database. It also provides a means for passing
SQL code to the database's interpreter for execution and a means
for retrieving data queried from the database.
- What database APIs work with nonrelational data sources?
OLE DB and ADO.
- What does an ADO Connection object do?
ADO Connection object encapsulates the functionality of logging
in to and out of a database, making queries, and retrieving resultsets.
- What does the current record mean?
The current record is the record at which the cursor in the recordset
is positioned.
- Change the code in Listing 4.12 so that the customers are
sorted by last name.
You need to change line 7 in Listing 4.12 to include an ORDER
BY clause on the last-name field.
- Change the code in Listing 4.12 to display the customer number
as well as the customer first and last name.
You need to add a column to the list control for the customer
number. You must also add a call to the Recordset GetCollect
function to retrieve the customer number field and store it in
a _variant_t. After the GetCollect call, you
can simply cast this _variant_t to a _bstr_t,
even though the original data type is numeric. _variant_t
and _bstr_t handle the conversion for you.
- What is a forward-only cursor?
A forward-only cursor is a cursor that moves only forward through
the resultset.
- What function do you use to place a value in a field of the
current record in an ADO Recordset?
The PutCollect function places a value in a field in
the current record of an ADO Recordset.
- What is wrong with this SQL statement?
DELETE FROM customers
Perhaps nothing is wrong with it. However, it's crucial to
note that this statement will delete every record in the Customers
table because it has no WHERE clause.
- What are the two arguments that you must pass to the ADO Recordset
AddNew function?
You must pass two arrays of VARIANTs, the first containing
the list of fields and the second containing the list of data
values to be placed in those fields.
- What happens if you specify only one field/value pair in the
SET clause of the SQL UPDATE function?
Only the data in that one field is updated. The other fields are
unchanged.
- Discover what happens in the Price field when you
specify only the PartNumber and ProductName
fields in a SQL INSERT statement for the Products
table, like this:
INSERT INTO Products(PartNumber, ProductName)
VALUES ('xxx', 'yyy')
The database will place a default value in the field. In this
case, zero is the default value for the Price field,
so zero will appear in the Price field of the new record.
- Modify the code in Listing 5.1 so that it doesn't specify
a price for the new record.
You need to change the CreateOneDim function call so
that the arrays have two elements instead of three. Then you delete
the code that defined the third elements (the Price field
name and data) in each array.
// Create an array for the list of fields in
// the Products table.
COleSafeArray vaFieldlist;
vaFieldlist.CreateOneDim(VT_VARIANT,2);
// Fill in the field names now.
long lArrayIndex[1];
lArrayIndex[0] = 0;
vaFieldlist.PutElement(lArrayIndex,
&(_variant_t("PartNumber")));
lArrayIndex[0] = 1;
vaFieldlist.PutElement(lArrayIndex,
&(_variant_t("ProductName")));
// Create an array for the list of values to go in
// the Products table.
COleSafeArray vaValuelist;
vaValuelist.CreateOneDim(VT_VARIANT,2);
// Fill in the values for each field.
lArrayIndex[0] = 0;
vaValuelist.PutElement(lArrayIndex,
&(_variant_t("8TRACK-003")));
lArrayIndex[0] = 1;
vaValuelist.PutElement(lArrayIndex,
&(_variant_t("Bell Bottom Hits")));
- What is a single-tier application?
A single-tier application consists of a single program that contains
all the code and logic, which runs in one process and tries to
accomplish all the work of the application.
- How do you make the SQL INSERT statement insert multiple
records?
You make the SQL INSERT statement insert multiple records
by replacing the VALUES clause with a SELECT
statement that returns multiple rows.
- What databases help you preserve the referential integrity
of your data?
The databases that help you preserve the referential integrity
of your data are relational database servers and Microsoft Access.
- How is a stored procedure in a relational database different
from a Query in Microsoft Access?
A Query in Microsoft Access is not compiled like a stored procedure.
A Query in Microsoft Access doesn't execute at the server like
a stored procedure. Also, a Query in Microsoft Access is treated
as a View in Visual Studio.
- Where can you find the data types available for use in ADO
Parameter objects?
You can find the data types available for use in ADO Parameter
objects in the ParameterDirectionEnum in msado15.tlh.
- Modify the SELECT statement in Listing 6.2 so that
the customer number is not hard-coded. Make it so that the customer
number is retrieved based on the customer's last name.
To retrieve the customer number based on the customers last name,
the SELECT statement needs to use a subquery. It would
look like this:
SELECT 4, { d '1998-11-16' },
(SELECT custnumber
FROM customers
WHERE custlastname = 'clinton'),
PartNumber, Price,
4, 'MC 1223 9873 2028 8374 9/99'
FROM Products
WHERE (PartNumber LIKE '8TRACK%')
- Add code to the OrderedSinceDate handler shown in
Listing 6.8 to change the value of the parameter after it has
been appended to the command but before the Command has been executed.
The code to change the value of a parameter attached to an ADO
Command object could look like this:
(pCommand->Parameters->GetItem(_variant_t("ParamDate")))
->PutValue(_variant_t(COleDateTime(1998, 11, 15, 0, 0, 0)));
- What is the highest normal form in the relational database
model?
The highest normal form in the relational model is the domain/key
normal form.
- What are entity relationships?
Entity relationships are the relationships between records in
various tables in a relational database.
- How can you guarantee that a table conforms to the second
normal form?
The second normal form requires that no fields apply to only part
of the primary key. If a table has a single key field, the table
is guaranteed of conforming to 2NF.
- What is the proper term for the structure (the tables, indexes,
constraints, and so on) of a relational database?
The structure of a relational database is called its schema.
- What does a referential integrity constraint do?
A referential integrity constraint ensures that the records related
through primary and foreign keys are not deleted independently
of each other. The constraint keeps the records in related tables
in synch with each other.
- Write a SELECT statement that shows all the products
purchased on each order. Hint: The SELECT statement should
perform a join between the NewOrders, ProductsPurchased,
and Products tables.
This SELECT statement shows all the products purchased
on each order:
SELECT neworders.ordernumber, products.productname
FROM neworders, productspurchased, products
WHERE neworders.ordernumber = productspurchased.ordernumber
AND productspurchased.partnumber = products.partnumber
- Write a SELECT statement showing the products purchased
by each customer.
This SELECT statement shows the products purchased by
each customer:
SELECT customers.custfirstname, customers.custlastname, products.productname
FROM neworders, productspurchased, products, customers
WHERE neworders.ordernumber = productspurchased.ordernumber
AND productspurchased.partnumber = products.partnumber
AND neworders.customernumber = customers.custnumber
- What are the ACID properties of a transaction?
The ACID properties of a transaction are atomicity, consistency,
isolation, and durability.
- What is the isolation level of a transaction?
The isolation level of a transaction is a setting in the database
that specifies how zealous it should be in protecting a user's
work from interaction with the work of other concurrent users.
- How does the GROUP BY clause interact with the SQL
aggregate functions?
Placing a GROUP BY clause with an aggregate function
in a SELECT statement causes the aggregate function to
perform its calculation on sets of records that are determined
by the GROUP BY clause.
- How many triggers can be attached to a table in Microsoft
SQL Server?
Three triggers can be attached to a table in Microsoft SQL Server:
an insert trigger, an update trigger, and a delete trigger.
- Does a view on a large table occupy much room in the database?
Why or why not?
A view on a large table doesn't occupy much room in the database
because the view stores no records. Only the SQL SELECT
statement that defines the view is stored in the database (and
a SELECT statement is relatively small).
- Modify the SELECT statement in Listing 8.7 so that
the resultset is sorted by the total sales volume, from the highest
volume to the least.
The code to sort the resultset in order to total sales, the highest
first, would look like this:
SELECT neworders.ordernumber,
SUM(price + shippingandhandling)
FROM neworders, productspurchased
WHERE neworders.ordernumber = productspurchased.ordernumber
GROUP BY neworders.ordernumber
ORDER BY SUM(price + shippingandhandling) DESC
- Modify the SELECT statement in Listing 8.7 so that
the query returns the average product price, from the highest
to the least.
The code to return the average product price, from the highest
to the least, would look like this:
SELECT neworders.ordernumber,
AVG(price)
FROM neworders, productspurchased
WHERE neworders.ordernumber = productspurchased.ordernumber
GROUP BY neworders.ordernumber
ORDER BY AVG(price) DESC
- Why can't you load a DLL into memory and send messages to
it from your app?
When your application loads a DLL into memory, the DLL becomes
part of your app. Your app cannot send messages (window messages
or otherwise) to the DLL and have the DLL act independent of your
application. The DLL code is mapped into your app's address space,
and any objects the DLL creates, your app owns.
- What makes a C++ class an abstract base class?
An abstract base class must have at least one pure virtual function
as a member. A pure virtual function is a function with =0
after its declaration.
- What is a class factory?
A class factory is a class that knows how to create instances
of a class that is a COM server. A class factory must be implemented
in every COM DLL and EXE. The class factory exposes a function
named CreateInstance, which the OS can call to get pointers
to instances of the COM servers whose code resides in that file.
- Why is it necessary for a COM client to call Release
on a COM server after it's finished with it?
The Release function decrements the usage count for that
COM object (the server). When the usage count reaches zero, the
server object is deleted or is told to delete itself. If no clients
are using a server object, it can and should be deleted to free
its resources.
- What is a CLSID, and why must all CLSIDs be unique?
A CLSID uniquely identifies a COM server. The CLSID is used in
the registry to store information on the location of the DLL or
EXE file that contains the COM server code. If there were duplicate
CLSIDs, there would be a chance that one CLSID could be overwritten
by another in the registry, preventing the first one from ever
being launched. Also, COM clients expect certain behavior and
support for certain interfaces from COM servers, based on the
CLSID. The uniqueness of the CLSID makes that expectation possible.
- Add another method to the IDbComponent interface.
Make this method take, as a parameter, an address to a variable
of some sort. Modify this variable in the server code and make
sure it gets back okay to the client.
The important thing for a parameter that is passed in to the server
to be modified and returned is that it be marked as [out]
in the Parameters edit box in the Add Method to Interface dialog.
- Use the ATL COM AppWizard to create a COM server in an EXE.
Expose a function in its interface that is similar to one in the
DLL COM server. Compare the performance of the EXE-based COM server
(the out-of-proc server) versus the DLL-based COM server (the
inproc server).
You should find that the out-of-proc server is much slower-has
much more function call overhead-than the inproc server.
- What is the goal or purpose of ODBC?
The goal or purpose of ODBC is to provide a uniform API for communicating
with relational databases from different vendors.
- How is ODBC's call-level interface different from embedded
SQL?
ODBC's call-level interface differs from embedded SQL in that
the SQL code in an ODBC application is not compiled by a precompiler
and translated to native database calls. Rather, the SQL code
in an ODBC application is interpreted at runtime by the database
(or by the database's ODBC driver).
- Where does the ADO type library reside and how can you view
it?
The ADO type library resides in the ADO DLL, which is called MSADO15.DLL
and is typically installed in the C:\Program Files\Common Files\System\ADO
directory. You can view the ADO type library by using the OLE-COM
Object Viewer included with Microsoft Visual Studio.
- Why does ADO throw exceptions when errors occur?
ADO throws exceptions when errors occur because that is how the
high-level ADO functions produced by #import are implemented.
The code for the high-level ADO functions can be found in the
MSADO15.TLI file.
- What function that you use with #import does not
throw exceptions but returns a failed HRESULT instead?
The smart pointer CreateInstance function doesn't throw
exceptions but returns a failed HRESULT in the case of
an error.
- Set break points in the inline functions in MSADO15.TLI, such
as the _Connection::Open function, and run ADOMFC1 in
debug mode to develop a feel for how code in MSADO15.TLH and MSADO15.TLI
is executed. Debug step into all the functions to discern when
you are executing code in your ADOMFC1 project and when you are
executing code in the ADO DLL
When you set breakpoints in the MSADO15.TLI file, you will find
that the functions with the raw_ prefix directly call
into the ADO library.
- Modify the code in Listing 10.7 so that the call to the ADO
Command Execute function in line 24 directly calls the
low-level Execute function.
The code for the Execute call should look like this:
22: _RecordsetPtr pRS;
23:
24: hr = pCommand->Raw_Execute( &vNull, &vNull, adCmdUnknown, Â&pRS );
- Interfaces and abstractions are the two pillars on which multitier
applications rest. Each tier that provides an effective level
of abstraction has interfaces that are understandable and distinct.
Distinct interfaces between the tiers enable the tiers to be updated
independently of each other.
- Thin client programs are often more desirable than fat clients,
because they do not require updates as often as fat client programs.
- HTML specifies how information will be displayed. XML specifies
what the data is and what it means.
- In a typical RDS application, the RDS DataControl
object is instantiated on the client machine in the browser's
process space. Often COM server(s) such as ActiveX controls are
also instantiated in the browser to enable a feature-rich UI.
The RDS DataControl object causes a DataFactory
object to be instantiated on the middle tier (Web server) machine.
- The security risk posed by the RDS COM servers is caused by
the fact that the DataFactory object can be instantiated on a
Web server machine. This can provide access to the database to
anyone on the Web who knows a valid data source, username, and
password for that database.
- DCOM alone is insufficient for building multitier applications
because DCOM by itself provides no support for transactions, thread
pooling, or database connection pooling. You would have to write
those features yourself to develop a multitier application with
just DCOM and without MTS.
- [out, retval] is the specification in IDL for a parameter
that is the return value of the method.
- Yes, MTS will run on Windows 98, if the machine has at least
32MB of RAM.
- Each MTS package specifies a process in which MTS components
are to run. This enables process isolation, as well as common
security settings for the collection of components that reside
in the package.
- A disconnected Recordset is an ADO Recordset that contains
data but currently has no a connection to a database. Disconnected
Recordsets can be sent between COM servers and clients as a flexible
and powerful data structure.
- The linker will produce an error because it cannot open the
DLL file for writing. This is because the DLL is loaded. To fix
the problem, you need to click the Refresh button on IE4 or exit
IE4 completely. Sometimes even this does not work. At those times,
you need to shut down the server processes using the Transaction
Server Explorer by right-clicking My Computer and selecting Shutdown
Server Process.
- Run the Transaction Server Explorer and navigate to the package
that contains MTSComp1.Component1. Select MTSComp1.Component1
and press the Delete key to remove the component from MTS. To
register the DLL so that you can use it as a normal COM server,
enter regsvr32 MTSComp1.DLL from the DOS prompt in the
directory where the DLL resides. You might need to mark it safe
for scripting and initialization again.
- You can't store C++ objects in relational database fields
because the only things that the database lets you store in fields
are instances of the data types that exist in the database's type
system.
- You can't use SQL for object-oriented programming because
the language has no object constructs or mechanisms. Its sole
purpose is to manipulate data in two-dimensional tables inside
relational databases.
- C++ object databases directly support the C++ type system,
including types (classes) that programmers create themselves.
Data in C++ object databases is accessible only to C++ programs
that understand the types (the classes) that are stored therein.
A relational database supports only the data types that it defines.
The data in relational databases is accessible to any application
that can understand the relational model and that can map between
its type system and the database's type system.
- When you are designing an application that will use object
and relational technology, it is generally best to start by designing
the relational database schema. You can then use the schema as
the basis for the object schema.
- The benefits of a live object cache include greatly improved
application performance because of reduced database access, and
reduced network traffic, again because of reduced database access.
- This SELECT statement retrieves the shoe type based
on the shoe ID from the Shoes table.
SELECT ShoeType
FROM Shoes
WHERE ShoeID = 1
- This SELECT statement shows the products purchased
by each customer.
SELECT Shoes.*, BasketballShoes.*
FROM Shoes, BasketballShoes
WHERE Shoes.ShoeID = BasketballShoes.ShoeID
- CDatabase
- The environment handle saves information necessary for the
application to connect to a data source. The Driver Manager will
construct the handle and then give the connected driver a copy.
- dbDBEngine. No
- CRecordSet::dynaset
- You can find the DAO classes in the OLE/COM Object Viewer
by expanding the All Objects element in the tree control in the
left window pane. The DAO classes all start with DAO.
To view the type information, double-click one of the classes
to instantiate the object, double-click one of the non-IUnknown
interfaces, and click the View Type Info button.
- The Record Field Exchange (RFX) implemented by DoFieldExchange().
- The document class contains the recordset. The Document in
the MFC Document/View architecture represents the application's
data store, whereas the View is a window to that data.
- OnInitialUpdate
- CRecordSet::dynaset
- The edit boxes should match the field declarations in the
AddressBook database. Yes, the fields are updated whenever
the cursor is moved. This is accomplished via the Record Field
Exchange (RFX) implemented by DoFieldExchange(). The
ODBC wrappers implement the cursor as part of the recordset, and
the View automatically creates a message interface from the cursor
buttons to the recordset's cursors.
- Identical to answer 1.
- The code should look something like this:
rs.AddNew();
rs.m_Last_Name = "Smith";
rs.m_First_Name = "Jennifer";
rs.Street = "234 WayWay St.";
rs.m_City = "Columbus";
rs.m_State = "OH";
rs.m_Zip = 45400;
rs.m_Phone = "614-5550101";
rs.Update();
- What are the two basic OLE DB components?
A data provider and a data consumer. A data provider is an application
that responds to queries and returns data in a usable form. A
data consumer is an application, or other COM component, that
uses the OLE DB API to access a data source.
- How does OLE DB currently enable access to ODBC data sources
for which no OLE DB provider is yet available?
The OLE DB SDK contains an OLE DB provider for ODBC data, called
MSDASQL, which allows you to access ODBC data sources
from OLE DB consumer applications. The OLE DB provider for ODBC
resides in MSDASQL.DLL.
- What are the major OLE DB objects?
The OLE DB. The major OLE DB components are called CoTypes. The
OLE DB CoTypes are TDataSource, TDBSession,
TCommand, TRowset, TIndex, TErrorObject,
and TTransaction.
- Which header files must be included to access OLE DB objects?
The header files OLEDB.H and OLEDBERR.H must be included for OLE
DB applications. These header files are used to include the OLE
DB classes and OLE DB error-handling classes, respectively.
- What is the URL for the OLE DB home page?
The URL of the OLE DB Web site is http://www.microsoft.com/data/oledb/.
- What is the role of a data provider and a data consumer in
the OLE DB architecture?
A data provider is a COM component that provides an OLE DB-compliant
interface. A data consumer is an application or component that
uses an OLE DB interface to access a data source.
- What is an interface? How does the COM architecture use an
interface?
Interfaces describe the functionality provided by the component
and also provide the structured mechanism that these components
use to talk with each other. A COM component is an object that
uses the rules in the COM specification to provide access to the
interfaces provided by a component.
- What is interface factoring?
Interface factoring is the capability of COM objects to support
multiple interfaces, which can provide different levels of functionality,
depending on the consumer. A consumer uses the interface appropriate
to its needs.
- What method is used to determine whether a COM object supports
a particular interface?
The interfaces supported by a COM component can be determined
by calling the QueryInterface method. When an application
determines whether a component supports a specific interface,
it is guaranteed the functionality of that interface.
- Describe the basic flow of information in an OLE DB application.
The consumer application uses the Enumerator object to
determine which OLE DB data source providers are available. It
then creates a DataSource object and uses the DataSource
object to create a Session object. Then the application
uses the Session object to create a Command
object. The application uses the Command object's Execute
function to create a Rowset object. Next, the application
navigates through the Rowset containing the data. Finally,
the application releases the objects.
- What is an Enumerator object, and how is it used?
The Enumerator class retrieves information regarding
all the OLE DB providers available on the system.
- What interfaces are supported by an Enumerator object?
The Enumerator object supports the following interfaces:
IparseDisplayName, IsourcesRowset, IDBInitialize,
IDBProperties, and IsupportErrorInfo.
- What is a DataSource object, and how is it created?
The DataSource object abstracts the actual data source.
It is created by binding a moniker returned from the Enumerator
class or by directly calling CoCreateInstance, using
the appropriate CLSID.
- What interfaces does a DataSource object support?
The DataSource object supports the following interfaces:
IDBCreateSession, IDBInitialize, IDBProperties,
Ipersist, IDBDataSourceAdmin, IDBInfo,
IpersistFile, and IsupportErrorInfo.
- What methods initialize and release the DLLs required by a
COM application?
The CoInitialize and CoUninitialize functions
load and release the appropriate COM-related DLLs. You must call
these functions at the start and end of any application that uses
COM.
- Review the Visual C++ books online documentation (provided
with Visual C++) for more information regarding the specifics
of COM programming.
Several places in the online documentation deal with COM. The
best way to find them is to search for terms such as COM,
QueryInterface, and OLE DB. When you find a useful
article (or document), press the Locate button to find that article
in the table of contents. Often you will find other useful information
in the neighboring documents.
- The applications developed yesterday and today do not really
consider error handling. How would you integrate error handling
into the application in Listing 17.4? (Hint: Most of the
COM related functions return an HRESULT type value.)
You should always check the value of the HRESULTs returned
by COM functions.
- The Session object provides a context for transactions
and commands. A Session object is created by using the
IDBCreateSession interface of the DataSource
object. The CreateSession method of this interface actually
creates a session. You can use the Session object to
create a Command object, to access a row set directly,
and to create or modify data source tables and indexes.
- The IDBSchemaRowset retrieves data source schema
information. Schema information describes the data contained in
the data source. The IDBSchemaRowset interface is optional
for Session objects.
- The Command object performs commands that the provider
supports. Using the SQL Server data provider (or even the OLE
DB ODBC provider) and a database such as SQL Server, you can use
the Command object to execute SQL commands. OLE DB data
providers aren't required to support commands.
- The ICommandText interface sets and retrieves the
actual command text, which specifies the data source command to
execute. The Command object requires the ICommandText
interface.
- In SQL, parameters in commands are usually specified with
the ? placeholder. The actual
parameter value replaces the ?.
Parameterized statements are similar to procedures in any programming
language; they are useful for executing a particular statement
repeatedly. A parameterized statement can execute a command whose
parameters are specified while an application is running.
- The ICommandPrepare interface converts a command
to a prepared command. A prepared command is a command that has
been precompiled so that it can execute faster. If you expect
a command to be executed repeatedly, transforming it into a prepared
command can improve application performance.
- List the major property groups.
The major property groups are DBPROPSET_COLUMN_DATASOURCE,
DBPROPSET_DATASOURCEINFO, DBPROPSET_DATAINIT,
DBPROPSET_INDEX, DBPROPSET_ROWSET, DBPROPSET_SESSION,
and DBPROPSET_TABLE. These groups are used to group properties
in the DBPROPIDSET and DBPROPSET structures.
- What structure returns the collection of property values?
The DBPROPSET structure holds the collection of property
values when retrieving and setting properties.
- Name the property that determines the level of SQL command
support provided by an OLE DB data provider?
The DBPROP_SQLSUPPORT property determines the level of
SQL command support provided by an OLE DB data provider.
- What method opens a transaction?
The StartTransaction method opens a transaction.
- What isolation level maintains the most consistent access
to a row set in a multiuser environment?
The ISOLATIONLEVEL_SERIALIZABLE flag specifies the serializable
isolation level, which offers the highest level of data integrity
inside a transaction.
- What property ensures that a row set is retained in a valid
state after a transaction is closed?
The Rowset property DBPROP_COMMITPRESERVE determines
the state of a row set when a transaction is committed or aborted.
If true, the row set is resynchronized to reflect the
results of the transaction; otherwise, the row set becomes invalid.
- What Index object method searches for a specific
key value in an index The Seek method of the Index
object searches for a specific key value.
- Name the two macros used to check the result of an OLE DB
method call.
Visual C++ provides two macros that can determine generally whether
a method was successful. These macros are SUCCEEDED and
FAILED. As you can tell by their names, the SUCCEEDED
macro returns true if the call to the method is successful,
and the FAILED macro returns true if the call
to the method is not successful.
- Which interface checks whether an OLE DB object supports extended
error information?
The IsupportErrorInfo interface determines whether an
object supports the necessary interfaces to retrieve additional
error information. The IsupportErrorInfo defines a single
method, InterfaceSupportsErrorInfo, that returns S_OK
if additional error information is supported.
- What are the special requirements of OLE DB error handling
that aren't resolved by Automation error-handling objects?
The OLE DB has two requirements that the standard IerrorInfo
interface does not meet:
- OLE DB must return provider-specific error information.
- OLE DB must return multiple error values at the same time,
but the IerrorInfo interface can return information
regarding one error only.
- What information does the GetBasicErrorInfo method
return? Describe the elements of this structure.
The GetBasicErrorInfo method retrieves the basic ERRORINFO
structure for the record number specified in the 1RecNum
parameter. The ERRORINFO structure holds basic information
about an error.
- How do you retrieve a custom error object? What custom error
objects does OLE DB provide?
The GetCustomErrorObject method retrieves a provider-specific
custom error. OLE DB provides one custom error interface for providers
that support the SQL command language: ISQLErrorInfo.
The ISQLErrorInfo method returns the current SQL status
and error value. The dwMinor field contains a provider-specific
error value. The clsid field contains the class ID of
the OLE DB object that generated this error. The iid
parameter contains the interface ID of the interface that generated
this error. The dispid field contains the method that
generated the error.
- List the basic techniques for OLE DB error handling.
The basic error-handling techniques are the following:
- Check the HRESULT value of a method when
it is called.
- If the method did not succeed, possibly print some error information.
- If the error is critical to the execution of the application,
gracefully end the application. Be sure to release any allocated
memory and close any open data sources and files.
- If the error is not critical (perhaps the data provider doesn't
support a specific method), dynamically change the functionality
of the application. For example, an application feature might
not be available with lower-level data providers.
- Which method does a data provider use to add a new error?
Data providers use the AddErrorRecord method to add new
error records.
- Explain the difference between HRESULT constants
with the prefix DB_S and those with the prefix DB_E.
HRESULT constants that begin with S or DB_S
are values that indicate success, and HRESULT constants
that begin with E or DB_E are error value constants.
© Copyright, Sams Publishing. All
rights reserved.