PDA

Ver la Versión Completa : Capacidad WideString


LauraAS
07-11-2007, 14:27:16
Hola, he implementado un WebService en Delphi7 que a través de una interface permite realizar una serie de operaciones o funciones que devuelven un texto xml (en una variable wide string) construido a partir de consultas a la BD MSSqlServer2000 utilizando ADOStoredProc.

Pero hay una función que me falla debido a que el data set devuelto es muy superior a la capacidad para albergarlo en un widestring y como está dentro del buche while not eof del StoredProc pues se me queda "colgado" el programa cliente. Pero las demás funcionan perfectamente porque el dataset devuelto es mucho menor en tamaño.

He de devolver un texto, puesto que es una interface de un webservice que ha de devolver un xml, y que yo sepa el máximo en Delphi es el WideString. ¿Cómo se puede solventar este problema? Digo yo que ha de haber algún modo de convertir a texto consultas enormes como en caso de listar las poblaciones de una provincia o de un pais.

El código es más o menos como sigue:

TQryTablas = class(TInvokableClass, IQryTablas)
public
fGetPoblaciones(codProvincia: string): WideString;
end;

...

function TQryTablas.fGetPoblaciones(codProvincia: string): WideString;
var xmlOut: WideString;
codError: integer;
WebModule1: TWebModule1;
begin
result:='<?xml version="1.0" encoding="ISO_8859-1"?>';
result:=result+'<fGetPoblacionesResponse>';
result:=result+'<errores>';
try
WebModule1:=TWebModule1.Create(nil);
codError:=WebModule1.cargarPoblaciones(codProvincia,xmlOut);
if codError=-1 then
begin
result:=result+'<error>';
result:=result+'<coderr>002</coderr>';
result:=result+'<descerr>'+K_002+'</descerr>';
result:=result+'</error>';
end
else if codError<>0 then
begin
result:=result+'<error>';
result:=result+'<coderr>001</coderr>';
result:=result+'<descerr>'+K_001+'</descerr>';
result:=result+'</error>';
end;
result:=result+'</errores>';
result:=result+xmlOut;
result:=result+'</fGetPoblacionesResponse>';
finally
WebModule1.Free;
end;
end;


...............

function TWebModule1.CargarPoblaciones(codProvincia: string; var xml: WideString): integer;
begin
xml:='<poblaciones>';
with SPQryPoblacion do
begin
Parameters.ParamByName('@cod_provincia').Value:=codProvincia;
Parameters.ParamByName('@cod_error').Value:=0;
Active:=True;
result:=Parameters.ParamByName('@cod_error').Value;
if result=0 then
begin
First;
while not EOF do
begin
xml:=xml+'<poblacion>';
xml:=xml+'<codigo>'+FieldByName ('COD_POBLACION').AsString+'</codigo>';
xml:=xml+'<codprovincia>'+FieldByName('COD_PROVINCIA').AsString+'</codprovincia>';
xml:=xml+'<nombre>'+FieldByName('NOMBRE_POBLACION').AsString+'</nombre>';
xml:=xml+'<codpostal>'+FieldByName('COD_POSTAL').AsString+'</codpostal>';
xml:=xml+'</poblacion>';
Next;
end;
end;
end;
xml:=xml+'</poblaciones>';
end;

dec
07-11-2007, 14:31:47
Hola,

Yo diría que el problema ha de estar en otro lado, puesto que "WideString" pude albergar cadenas de hasta 2 GB...

Por cierto, edita tu mensaje para añadir etiquetas (http://www.clubdelphi.com/foros/misc.php?do=bbcode) a tu código con el fin de resaltarlo.

Y, por favor, revisa la guía de estilo de estos Foros. Y sé bienvenida a ellos. :)

LauraAS
07-11-2007, 14:49:40
He probado a restringir la consulta sql con un "select top 100 from poblacion where cod_provincia=@cod_provincia" y funciona perfectamente.

El problema sucede con solo determinadas provincias que tienen demasiadas poblaciones: asturias(cod_provincia='033'), galicia, etc. Con lo cual yo lo achaco a un problema de tamaño, y solo nos queda el widestring porque el dataset está claro que lo alberga. Estamos hablando de 20.000 o más registros devueltos en alguno de estos casos. Aparte ya he probado la consulta sola mostrándola en un DBGrid y aunque tardaba unos 12 seguntos, la mostraba bien. Como no sea un problema de la interface importada por el programa cliente... no se ya que pensar...

Utilizo un programilla cliente de prueba que simplemente tiene un componente HTTPRIOR y importa la interface IQryTablas a partir del Wizar: File-->New-->Others -->WebServices-->WSDL Importer. Y a través del componente HTTPRIOR llama a la función fGetPoblaciones(codProvincia) guardando el resultado en un fichero .xml.

.......................

GrabarFichero(nomFichero,(HTTPRIO1 as IQryTablas).fGetPoblaciones
(codProvincia));


Y funciona siempre excepto para ciertos "codProvincia". Por eso me gustaría saber si alguien ha trabajado con grandes volúmenes de datos que ha de devolver un webservices.

Chris
07-11-2007, 15:42:41
Más o menos de que tamaño en bytes tiene el archivo xml devuelto, fijate que puede ser demaciado grande y que por ende el tiempo de espera se aumente.

Podrías talvez, utilizar otro método como por ejemplo utilizar una consulta normal y luego que el cliente convierta esa consulta a un tabla xml.

Saludos.

LauraAS
08-11-2007, 14:48:18
El problema está claro: intenta meter en un contenedor de caracteres más caracteres de los que puede albergar(2GB) dentro de un bucle while not eof, con el consiguiente "cuelgue" del programa. Necesito una tipo de datos que almacene texto, caracteres (es lo que tengo que devolver, xml) y que sea capaz de albergar más de 2 GB(más que un WideString o PWideChar) en Delphi 7.

Podéis probar vosotros mismos a intentar meter en nodos xml dentro de un tipo Wide String, unos 15000 registros que devuelve una tabla, teniendo en cuenta que cada uno de los campos de un registro representaría un nodo diferente. Así pues sería algo como sigue el xml:

<listadoTabla>
<registro1>
<campo1/>
...
<campoN/>
</registro1>
....

<registroN>
<campo1/>
...
<campoN/>
</registroN>
</listadoTabla>


No es muy dificil de imaginar que el xml resultante de hacer esto con 5000, 10000 o más registros se exceda de la capacidad de 2GB del WideString.

Y bien, este es mi problema... Se aceptan sugerencias

tefots
08-11-2007, 16:59:54
Has de devolver un widestring por narices ?
por que no usar un pchar ?.
eso si , igual tienes que reservar x bytes maximo , digamos 4gybtes y controlar que no te excedas de esos bytes.

Aun asi , me parece una barbaridad , deberias paginar los resultados , devolviendo solo n filas o n nodos , ya que como te hagan varias consultas de esas a la vez , el servidor lo saturas y lo dejas frito de memoria.

podrias ampliar el servicio pidiendole la pagina x , asi el servicio solo meteria en el widestring n nodos/registros de dicha pagina , (incluso podria devolver el nº de paginas que tiene ), para que así el cliente sepa cuantas paginas puede pedir.

saludos.
Saludos