Ajuda com Tres Camadas
Senhores, tenho uma dúvida. Estou melhorando um sistema em Tres Camadas na minha empresa.
Essa melhore é retirar todos os CommandText do lado cliente e colocar no lado Servidor de Aplicação.
Só que me deparei om um pequeno probleminha. Nesse select eu tenho um IF. Caso uma situação do IF
for atendida então o Select tem um AND..., caso contrário não. Como esse Selecet é partido em duas partes
antes e depois do IF, tenho um dúvida de como fazer. Lembrando que o IF é somente no lada Cliente. Não
tem como colocá-lo no lado Servidor, por razões óbvias, senão deixaria de ser Tres Camadas. Abaixo o
Select como está hoje.
Essa melhore é retirar todos os CommandText do lado cliente e colocar no lado Servidor de Aplicação.
Só que me deparei om um pequeno probleminha. Nesse select eu tenho um IF. Caso uma situação do IF
for atendida então o Select tem um AND..., caso contrário não. Como esse Selecet é partido em duas partes
antes e depois do IF, tenho um dúvida de como fazer. Lembrando que o IF é somente no lada Cliente. Não
tem como colocá-lo no lado Servidor, por razões óbvias, senão deixaria de ser Tres Camadas. Abaixo o
Select como está hoje.
´SELECT ´ +
´ SEC.CDG_SECAO,PROD.CDG_PRODUTO,PROD.DESC_PRODUTO,PA.CDG_PRODUTO, ´ +
´ PA.MES_ESTOQUE_PA,PA.CDG_COR,CDG_TAM, ´ +
´ (PA.QTDE_ESTOQUE_PA + PA.QTDE_ESTOQUE_PA_OUT) PECAS ´ +
´ FROM ´ +
´ TB_CTRL_PRODUTO PROD, TB_CTRL_ESTOQUE_PA PA, TB_CTRL_SECAO SEC ´ +
´ WHERE ´ +
´ PROD.CDG_PRODUTO = PA.CDG_PRODUTO AND PA.CDG_SECAO = SEC.CDG_SECAO´;
if (rbProdEsp.Checked = True) and (LKP_Produto.Text <> ´´) then
Sql := Sql + ´ AND PROD.CDG_PRODUTO = ´ + LKP_Produto.Text;
Sql := Sql +
´ ORDER BY ´ +
´ PROD.CDG_PRODUTO,PA.CDG_PRODUTO,PA.MES_ESTOQUE_PA, ´ +
´ PA.CDG_COR, PA.CDG_TAM´;
Paulo
Curtidas 0
Respostas
Fabianosales
14/07/2008
Uma maneira direta de fazer isso, seria criar dois providers e duas queries no servidor de aplicações, porém, muito embora isso resolva o problema, o desperdício de recursos nessa abordagem é obvio (sempre haverá pelo menos dois componentes não utilizados, um DataSetProvider e um SQLQuery, por exemplo).
Um outro jeito (menos simples e mais correto), seria criar um método publicado no RemoteDataModule que receberia os parâmetros, montatia a query e retornaria o nome do provider ao qual o ClientDataSet local deveria se conectar.
Um outro jeito (menos simples e mais correto), seria criar um método publicado no RemoteDataModule que receberia os parâmetros, montatia a query e retornaria o nome do provider ao qual o ClientDataSet local deveria se conectar.
GOSTEI 0
Paulo
14/07/2008
A primeira hipótese foi a que eu fiz. Isso eu não quero, pois requer duplicação de códigos, praticamente, mas atualmente está assim. A segunda deve ser a mais correta, pois minhas funcções estão assim, ou seja, um método somente para executá-las e receber parâmetros dos Clientes, mas não pensei em fazer com Querys simples.
GOSTEI 0
Luiz Henrique
14/07/2008
Paulo Bom dia, tudo blz...vamos compartilhar entao...
Tenho uma funcao que uso para isto, ´meio geral´ para SQL com determinada ´magnitude´...retorna sempre a consulta no formato CDS.Data, assim pode ser ainda analisado no cliente, se for o caso:
//Servidor
function RetornaSQL(nID: Double; aParametros: OleVariant): OleVariant;
safecall;
nID: Constantes identificadoras da requisicao SQL, exemplo: ANALISE_VENDAS_VENDEDOR_SINTETICO,
DC_REL_DUPL_MERCANTIL e etc...
aParametros: um array of OleVariant, assim passo qualquer tipo de parametro e sem limite...
Uso sempre uma especie de ´interface´ no cliente, para este caso é essencial, no cliente voce trata a chamada antes de passar para o servidor. Exemplo no teu caso:
formulario/cliente:
CDS.Data:= MeuDMCliente.RetornaSQL(PRODUTOS_ESTOQUE,[rbProdEsp.Checked, LKP_Produto.Text]);
//Converte a array em OleVariant e executa o metodo no Servidor.
Function MeuDMCliente.RetornaSQL(_id_sql: Double;
aParametros: array of OleVariant): OleVariant;
var
i, ii : Integer;
ParArray : OleVariant;
begin
ii := 0;
for i := Low( aParametros ) to High( aParametros ) do begin
inc( ii );
end;
//Cria Array de Parametros
if ii > 0 then begin
ParArray := VarArrayCreate( [ 0, ii -1 ], varVariant );
ii := 0;
for i := Low( aParametros ) to High( aParametros ) do begin
ParArray[ ii ] := aParametros[ i ];
inc( ii );
end;
end
//Funcao sem Parametros, informa...
else begin
ParArray := VarArrayCreate( [ 0, 1 ], varVariant );
ParArray[0]:= Null;
end;
Result:= SConPrincipal.AppServer.ClasseRelatorio.RetornaSQL(_id_sql,
ParArray);
end;
//No servidor...teu metodo publico declarado ....fica assim
...RetornaSQL(nID: Double;
aParametros: OleVariant): OleVariant;
var
//As variaveis a titulo de ilustracao e facilitar o exemplo
//Poderam ser mais ´genericas´ para serem usadas nas outras
// SQL da rotina, e nao ficar declarando um caminhao de variaveis
// para cada SQL implementada na funcao.
bProdEsp: boolean;
sLKP_Produto: string;
begin
if nID = PRODUTOS_ESTOQUE then begin
bProdEsp:= aParametros[0];
sLKP_Produto:= aParametros[1];
....monta/trata/retorna teu SQL
end
else if nID ......Outras requisicoes
....
Funcao bem dinamica pela array de parametros...
Espero que ajude, Abraço T+
Tenho uma funcao que uso para isto, ´meio geral´ para SQL com determinada ´magnitude´...retorna sempre a consulta no formato CDS.Data, assim pode ser ainda analisado no cliente, se for o caso:
//Servidor
function RetornaSQL(nID: Double; aParametros: OleVariant): OleVariant;
safecall;
nID: Constantes identificadoras da requisicao SQL, exemplo: ANALISE_VENDAS_VENDEDOR_SINTETICO,
DC_REL_DUPL_MERCANTIL e etc...
aParametros: um array of OleVariant, assim passo qualquer tipo de parametro e sem limite...
Uso sempre uma especie de ´interface´ no cliente, para este caso é essencial, no cliente voce trata a chamada antes de passar para o servidor. Exemplo no teu caso:
formulario/cliente:
CDS.Data:= MeuDMCliente.RetornaSQL(PRODUTOS_ESTOQUE,[rbProdEsp.Checked, LKP_Produto.Text]);
//Converte a array em OleVariant e executa o metodo no Servidor.
Function MeuDMCliente.RetornaSQL(_id_sql: Double;
aParametros: array of OleVariant): OleVariant;
var
i, ii : Integer;
ParArray : OleVariant;
begin
ii := 0;
for i := Low( aParametros ) to High( aParametros ) do begin
inc( ii );
end;
//Cria Array de Parametros
if ii > 0 then begin
ParArray := VarArrayCreate( [ 0, ii -1 ], varVariant );
ii := 0;
for i := Low( aParametros ) to High( aParametros ) do begin
ParArray[ ii ] := aParametros[ i ];
inc( ii );
end;
end
//Funcao sem Parametros, informa...
else begin
ParArray := VarArrayCreate( [ 0, 1 ], varVariant );
ParArray[0]:= Null;
end;
Result:= SConPrincipal.AppServer.ClasseRelatorio.RetornaSQL(_id_sql,
ParArray);
end;
//No servidor...teu metodo publico declarado ....fica assim
...RetornaSQL(nID: Double;
aParametros: OleVariant): OleVariant;
var
//As variaveis a titulo de ilustracao e facilitar o exemplo
//Poderam ser mais ´genericas´ para serem usadas nas outras
// SQL da rotina, e nao ficar declarando um caminhao de variaveis
// para cada SQL implementada na funcao.
bProdEsp: boolean;
sLKP_Produto: string;
begin
if nID = PRODUTOS_ESTOQUE then begin
bProdEsp:= aParametros[0];
sLKP_Produto:= aParametros[1];
....monta/trata/retorna teu SQL
end
else if nID ......Outras requisicoes
....
Funcao bem dinamica pela array de parametros...
Espero que ajude, Abraço T+
GOSTEI 0
Paulo
14/07/2008
Olá Luiz, vou testar hoje sua função e posto o Result da mesma. Valeu!!!
GOSTEI 0