⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dbcommand.cpp_1

📁 Vc.Net入门与提高源码
💻 CPP_1
📖 第 1 页 / 共 2 页
字号:
// File: dbcommand.cpp_1
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Classes Reference and related electronic
// documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft C++ Libraries products.

#include "StdAfx.h"
#include "dbcommand.h"

DBCommand::DBCommand(IResultsBuilder *builder)
{
	m_pResultBuilder = builder;
	m_arrParams = NULL;
}

DBCommand::~DBCommand(void)
{
	Clean();
	m_pResultBuilder = NULL;
}

void DBCommand::Clean()
{
	if (m_arrParams)
		delete[] m_arrParams;
	m_arrParams = NULL;
}

HRESULT DBCommand::GetCmdInfo(	CStringA&		cmdName,
								CStringA&		connectionString, 
								IMemoryCache	*spBinaryCache,
								const CSession  &session, 
								CmdInfo			**cmdInfo, 
								bool&			infoFromCache)
{
	HRESULT hr = S_OK;

	CProcedureParameters procInfo;

	if (spBinaryCache == NULL)
	{
		hr = CreateAndStoreCmdInfo(	procInfo, 
									session, 
									spBinaryCache, 
									cmdName, 
									connectionString, 
									cmdInfo, 
									infoFromCache);
		
		ASSERT(!FAILED(hr));
		if (FAILED(hr))
		{
			// if we can't get cmd information, nothing to do but return
			return hr;
		}		
	}
	else
	{
		// we do have a cache, see if our cmd info is in it
		HANDLE hEntry;
		if (SUCCEEDED(spBinaryCache->LookupEntry(cmdName + connectionString, &hEntry)))
		{
			DWORD dwSize = 0;	
			hr = spBinaryCache->GetData(hEntry, (void**)*cmdInfo, &dwSize);

			if (FAILED(hr))
			{
				// if we couldn't get the command info from the cache, create it
				// ourselves
				hr = CreateAndStoreCmdInfo(	procInfo, 
											session, 
											spBinaryCache, 
											cmdName, 
											connectionString, 
											cmdInfo, 
											infoFromCache);
		
				ASSERT(!FAILED(hr));
				if (FAILED(hr))
				{
					// if we can't get cmd information, nothing to do but return
					return hr;
				}		
			}
			else
			{
				// getting here means we got our cmd information from the 
				// cache successfully, all we have to do is set the flag
				// so nobody deletes this value
				infoFromCache = true;

				// close our handle
				CloseHandle(hEntry);
			}
		}
		else
		{
			// if there was nothing in the cache, we'll have to create things on our own
			hr = CreateAndStoreCmdInfo(	procInfo, 
										session, 
										spBinaryCache, 
										cmdName, 
										connectionString, 
										cmdInfo, 
										infoFromCache);
		
			ASSERT(!FAILED(hr));
			if (FAILED(hr))
			{
				// if we can't get cmd information, nothing to do but return
				return hr;
			}		
		}
	}	
	return hr;
}

void DBCommand::IterateRowset(CommandType&	command,
							  ULONG			ulColumns,
							  struct MYBIND* pBind)
{	
	long rowsAffected = 0;

	// get the rowset items	
	while (command.MoveNext() == S_OK)
	{
		for (ULONG j = 1; j <= ulColumns; j++)
		{
			if (pBind[j-1].dwStatus == DBSTATUS_S_ISNULL)
				_tcscpy(pBind[j-1].szValue, _T(""));

			m_pResultBuilder->AddColumnValue(CStringA(pBind[j-1].szValue));
		}			
		m_pResultBuilder->DoneRow();
	}	
}

HRESULT DBCommand::GetResults(CommandType& command, int numParams)
{	
	HRESULT hr = S_OK;
	LONG lRows = 0;

	// Get the column information and bind the output columns.
	ULONG           ulColumns = NULL;
	DBCOLUMNINFO*   pColumnInfo = NULL;
	OLECHAR*        pColumnNames = NULL;
	OLECHAR**       ppNames;
	struct MYBIND*  pColumns    = NULL;
	
	// this loop will handle stored procs that handle multiple result sets
	do 
	{		
		if (command.m_spRowset != NULL)	
		{			
			ulColumns	 = NULL;
			pColumnInfo	 = NULL;
			pColumnNames = NULL;			
			pColumns     = NULL;

			hr = command.GetColumnInfo(&ulColumns, &pColumnInfo, &pColumnNames);
	
			if (FAILED(hr))
				return hr;
	
			if (ulColumns > 0)
			{
				ppNames = new OLECHAR*[ulColumns];
				pColumns = new MYBIND[ulColumns];
				
				command.CreateAccessor(ulColumns, &pColumns[0], sizeof(MYBIND)*ulColumns);
				
				for (ULONG l = 0; l < ulColumns; l++)
				{
					ppNames[l] = pColumnNames;
					if (*pColumnNames)
					{
						while(*pColumnNames++);
					}	
					command.AddBindEntry(l+1, 
										DBTYPE_STR,
										sizeof(TCHAR)*MAX_SIZE, 
										&pColumns[l].szValue,
										NULL, 
										&pColumns[l].dwStatus);
				}
			}
			// bind our command to get column, output parameter and return values
			command.Bind();
	
			// iterate over our results			
			IterateRowset(command, ulColumns, pColumns);

			// we are finished with 1 result set, move on to the others
			Trace::TraceMsg("DBCommand done result set");
			m_pResultBuilder->DoneResultSet();
		
			// clean up
			CoTaskMemFree(pColumnInfo);
			CoTaskMemFree(pColumnNames);
			CoTaskMemFree(*ppNames);

			if (ppNames) 
			{
				delete[] ppNames;
				ppNames = NULL;
			}

			if (pColumns)
			{
				delete[] pColumns;
				pColumns = NULL;
			}
		}		
		lRows = 0;		
	}while (command.GetNextResult(&lRows, false) == S_OK);

	// TODO HACK, m_arrParams[i].dwStatus is not being set properly, workaround it
	// for now
	for (int i = 0; i < numParams; i++)
	{
		if (i == 0)
		{			
			m_pResultBuilder->SetReturnValue(CStringA(m_arrParams[i].szValue));
		}
		else if (m_arrParams[i].dwStatus == DBPARAMTYPE_RETURNVALUE)
		{
			m_pResultBuilder->AddOutputParamValue(CStringA(m_arrParams[i].szValue));
		}		
	}	
	return hr;
}

HRESULT DBCommand::ExecuteCommand(	const CSession&	session,						   
									CmdInfo			*cmdInfo,						   
									StringList&		inputParams)
{
	ASSERT(cmdInfo != NULL);

	if (cmdInfo == NULL)
	{
		return E_FAIL;
	}	

	USES_CONVERSION;
	HRESULT hr = S_OK;

	CommandType command;

	// create the command using our call string
	hr = command.Create(session, cmdInfo->cmdCallString);

	// only going to call this once
	hr = command.Prepare(1);

	// if this stored proc takes parameters pass them in
	int numParams = cmdInfo->paramTypes.GetCount();
	if (numParams > 0)
	{
		DBPARAMBINDINFO* bindInfo = new DBPARAMBINDINFO[numParams];
		ULONG* ordinals			  = new ULONG[numParams];		
		m_arrParams				  = new MYBIND[numParams];

		// make the bindings for the accessor based on the DBTYPE_STR data type
		command.CreateParameterAccessor(numParams, &m_arrParams[0], sizeof(MYBIND)*numParams);
				
		for (int l = 0; l < numParams; l++)
		{
			// Set up information for the SetParameterInfo call
			ordinals[l] = l+1;
			bindInfo[l].pwszDataSourceType = T2OLE(_T("DBTYPE_CHAR"));
			bindInfo[l].pwszName = NULL;					
			bindInfo[l].ulParamSize = MAX_SIZE;
			bindInfo[l].bPrecision = 0;
			bindInfo[l].bScale = 0;

			DWORD dwFlags = 0;
			
			if (cmdInfo->paramTypes[l] == DBPARAMTYPE_INPUT || 
				cmdInfo->paramTypes[l] == DBPARAMTYPE_INPUTOUTPUT)
					dwFlags |= DBPARAMFLAGS_ISINPUT;

			if (cmdInfo->paramTypes[l] == DBPARAMTYPE_OUTPUT ||
				cmdInfo->paramTypes[l] == DBPARAMTYPE_INPUTOUTPUT ||
				cmdInfo->paramTypes[l] == DBPARAMTYPE_RETURNVALUE)
					dwFlags |= DBPARAMFLAGS_ISOUTPUT;
			
			bindInfo[l].dwFlags = dwFlags;

			// Set up information for bindings
			if (cmdInfo->paramTypes[l] == DBPARAMTYPE_RETURNVALUE)
			{				
				command.AddParameterEntry(	1, 
											DBTYPE_STR, 
											sizeof(TCHAR)*MAX_SIZE,
											&m_arrParams[l].szValue, 
											NULL, 
											&m_arrParams[l].dwStatus, 
											DBPARAMIO_OUTPUT);
			}
			else
			{			
				command.AddParameterEntry(	l+1, 
											DBTYPE_STR, 
											sizeof(TCHAR)*MAX_SIZE,
											&m_arrParams[l].szValue, 
											NULL, 
											&m_arrParams[l].dwStatus, 
											cmdInfo->paramTypes[l]);
			}
		}				

		// call ICommandWithParameters::SetParameterInfo so that we can
		// tell the provider to convert the parameter types to DBTYPE_STR
		command.SetParameterInfo(numParams, ordinals, bindInfo);		

		// cleanup
		delete[] ordinals;
		delete[] bindInfo;
	}
		
	// put in our input parameters
	if (inputParams.GetCount() > 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -