Recordsets ADO Num Mundo de n-Camadas

Para criar aplicações altamente escaláveis, os recursos do servidor de dados e da camada intermediária devem ser liberados o mais rápido possível.

 

Marshalling

Você tem um objeto servidor que fornece recordsets desconectados

E um cliente que usa este servidor

Dim obj As New ADOServer.Data

Set rs = obj.getRS()

' faz algumas mudanças no recordset aqui

obj.setRS rs (atente para esta linha)

O que acontece quando o recordset é passado entre o cliente e o servidor?

Bem, depende ...

Quando ambos os objetos estão no mesmo processo, é passado um ponteiro.

Mas você não pode passar ponteiros entre fronteiras de processos ou máquinas.

- HTTP ou DCOM

No lugar, é usado Marshalling  (condução) para mover o recordset entre os processos.

Assuma que rs tem 5000 linhas.

- Set rs = obj.getRs ' isto toma 2.2 segundos

- Isto implica em passar uma vez o rs entre os processos.

- obj.setRS rs ' isto levará 4.4 segundos

- rs é passado em ambas as direções! 

Usando ByVal

Normalmente, o cliente não precisa ver qualquer mudança que o servidor tenha feito, portanto, modifique a definição da função do servidor para:

Public Funcion setRS ( ByVal rs As Recordset ) As Boolean

obj.setRS rs ' irá consumir 2.2 segundos agora

porque rs não é passado de volta para o cliente

Usando Opções de Marshalling

Habitualmente, o servidor precisa apenas saber os registros que o cliente modificou. Assim, no código cliente atribua:

rs.MarshalOptions = adMarshalModifiedOnly

obj.setRS rs ' irá consumir agora 0.2 segundos

Realizando uma atualização em batch

Se recordsets desconectados são atualizáveis, eles costumam usar o tipo de bloqueio BatchOptimistic.

- No MTS ou COM+, isto significa configurar o atributo de transação do componente que esteja fazendo as atualizações de modo que ele rode numa transação

- Fora do MTS ou COM+, isto significa fazer uso dos métodos de transação do objeto Connection

Codigo Mínimo Para Atualização em Batch

Public Function setRS(ByVal rs As Recordset) As Variant
On Error GoTo ErrH
 
rs.ActiveConnection = CONNECTION_STRING
rs.ActiveConnection.BeginTrans
rs.UpdateBatch
rs.ActiveConnection.CommitTrans
rs.ActiveConnection = Nothing
setRS = Null
Exit Function
ErrH:
setRS = Err.Description
rs.ActiveConnection.RollbackTrans
Set rs.ActiveConnection = Nothing
End Function

Pré e Pós-Processamento

É muito comum fazer-se algum pré-processamento (validação) e pós-processamento (tratamento de erros)

On Error Goto ErrH
rs.ActiveConnection.BeginTrans
validate(rs)
rs.UpdateBatch
rs.ActiveConnection.CommitTrans
Exit Function
ErrH:
processErrors(rs)
rs.ActiveConnection.RollbackTrans