Web Servis - sunucudan dataset göndermek
Forum kuralları
Forum kurallarını okuyup, uyunuz!
Forum kurallarını okuyup, uyunuz!
Web Servis - sunucudan dataset göndermek
Merhaba,
Web Servis konusuna çok yeniyim. Consume etme (client) kısmı ile ilgili sorunum yok (en azından şimdilik) ancak sunucu tarafında bulduğum tüm örnekler string veya integer gibi tek değer veya "TEmployee" gibi adı, soyadı, maaşı gibi tek kayıt gönderen örnekler.
Benim yapmak istediğim ise bir Query sonucunu (DataSet) karşı tarafa göndermek. Tabi bunu yaparken kayıtlar arasında tek tek dolaşıp her bir alanı XML haline çevirmeye çalışmadan çözüm üretmek istiyorum. Göndermem gereken veriler TDateTime, string, integer, float, boolean veriler içerebilir. TDateTime içinde milisaniye bilgisi dahil olabilir.
Nasıl yapılabileceği ile ilgili açıklama veya benim bulamadığım hazır bir örnek linki çok işime yarayacaktır.
Client ve Server tarafının ikisini de Delphi 10 ile ben hazırlayacağım.
Forum içinde referans olarak bulunması açısından:
Client kısmı için bulabildiğim en iyi örnek linki: http://edn.embarcadero.com/article/28631
Teşekkürler.
Web Servis konusuna çok yeniyim. Consume etme (client) kısmı ile ilgili sorunum yok (en azından şimdilik) ancak sunucu tarafında bulduğum tüm örnekler string veya integer gibi tek değer veya "TEmployee" gibi adı, soyadı, maaşı gibi tek kayıt gönderen örnekler.
Benim yapmak istediğim ise bir Query sonucunu (DataSet) karşı tarafa göndermek. Tabi bunu yaparken kayıtlar arasında tek tek dolaşıp her bir alanı XML haline çevirmeye çalışmadan çözüm üretmek istiyorum. Göndermem gereken veriler TDateTime, string, integer, float, boolean veriler içerebilir. TDateTime içinde milisaniye bilgisi dahil olabilir.
Nasıl yapılabileceği ile ilgili açıklama veya benim bulamadığım hazır bir örnek linki çok işime yarayacaktır.
Client ve Server tarafının ikisini de Delphi 10 ile ben hazırlayacağım.
Forum içinde referans olarak bulunması açısından:
Client kısmı için bulabildiğim en iyi örnek linki: http://edn.embarcadero.com/article/28631
Teşekkürler.
Re: Web Servis - sunucudan dataset göndermek
Eger stream gönderebiliyorsaniz datasetten dönen veriyi tclientdataset ile stream'a kaydedip gönderebilir akabinde karsi tarafta yine tclientdataset ile gelen stream'dan verileri okuyabilirsiniz.
kıdemsiz üye
Re: Web Servis - sunucudan dataset göndermek
Çok basit bir örnek istesem mümkün olabilir mi? Zira, Delphi yapabiliyor ise stream gönderebilirim. Ancak, nasıl yapılacağı ile ilgili fikrim yok maalesef.
Re: Web Servis - sunucudan dataset göndermek
Ben hic webservisler ile calismadim. Soketler ile calistim.
O nedenle cümleme "eger stream gönderebiliyorsaniz" seklinde basladim. Webservisde socket islemleri yapiyorsaniz metodunu kullanmaniz gerekir. Stream büyük olursa server tarafinda donma yasanabilir. Burada devreye thread ve pooling girer.
Webservis ile hic ugrasmadigim icin veri gönderimi ve alimi konusunda bilgiye sahip degilim. Yanlis bir yönlendirme yapip sizi cikmaza sürüklemek istemem.
O nedenle cümleme "eger stream gönderebiliyorsaniz" seklinde basladim. Webservisde socket islemleri yapiyorsaniz
Kod: Tümünü seç
socket.sendbuf
Webservis ile hic ugrasmadigim icin veri gönderimi ve alimi konusunda bilgiye sahip degilim. Yanlis bir yönlendirme yapip sizi cikmaza sürüklemek istemem.
kıdemsiz üye
Re: Web Servis - sunucudan dataset göndermek
Merhabalar ,
Şahsen web servsilerde geriye dataset döndürmem gereken durumlarda JSON formatında dönüyorum. verilen dataset i JSON olarak geri veren fonksiyon olarak aşağıdaki yapıyı kullanabilirsiniz.
Şahsen web servsilerde geriye dataset döndürmem gereken durumlarda JSON formatında dönüyorum. verilen dataset i JSON olarak geri veren fonksiyon olarak aşağıdaki yapıyı kullanabilirsiniz.
Kod: Tümünü seç
function DataToJSON(TableName: string;
Dataset: TDataset): string;
function CleanJSON( pRawData : String ) : String ;
var
intTemp : String ;
begin
intTemp := StringReplace( pRawData , '\' , '\\' , [rfReplaceAll] ) ;
intTemp := StringReplace( intTemp , '"' , '\"' , [rfReplaceAll] ) ;
intTemp := StringReplace( intTemp , #13#10 , ' ' , [rfReplaceAll] ) ;
intTemp := StringReplace( intTemp , #9 , ' ' , [rfReplaceAll] ) ;
intTemp := StringReplace( intTemp , #13 , '\r' , [rfReplaceAll] ) ;
intTemp := StringReplace( intTemp , #10 , '\n' , [rfReplaceAll] ) ;
Result:= intTemp;
end;
var
Data : string;
JSONEncodingFormat : string;
I : Integer;
FieldValue : string;
begin
Dataset.First;
while not Dataset.Eof do
begin
Data := Data + '{';
for I := 0 to Dataset.FieldCount - 1 do
begin
FieldValue := Dataset.Fields[I].AsString;
Data := Data + '"' + Dataset.Fields[I].FieldName + '":"' + CleanJSON( FieldValue ) + '"';
if I < Dataset.FieldCount - 1 then
Data := Data + ',';
end;
Data := Data + '},';
Dataset.Next;
end;
Delete(Data, Length(Data), 1);
JSONEncodingFormat := '{<Tablename>:[<Data>]}';
Result := StringReplace(JSONEncodingFormat, '<TableName>', '"'+TableName+'"', [rfIgnoreCase]);
Result := StringReplace(Result, '<Data>', Data, [rfIgnoreCase]);
end;
Volkan KAMADAN
www.polisoft.com.tr
www.polisoft.com.tr
Re: Web Servis - sunucudan dataset göndermek
Bulduğunuz örnekte ki web servisin sunucu tarafı .net ile geliştirilmiştir.ertank yazdı: Client kısmı için bulabildiğim en iyi örnek linki: http://edn.embarcadero.com/article/28631
Geriye Dataset döndürmektedir.
Dataset sınıfını incelediğimizde IXmlSerializable,ISerializable sınıflarını implemente ettiğini görmüş oluyoruz.
Yine bulduğunuz dokümanda Delphi tarafında;
Kod: Tümünü seç
rtnZipDSResult = class(TRemotable)
Anahtar kelimeler : IXmlSerializable,ISerializable,TRemotable
Re: Web Servis - sunucudan dataset göndermek
Biraz uğraştıktan sonra aşağıdaki gibi bir çözüm ile işimi gördüm sayılır. Anladığım kadarıyla platform bağımsız bir sistem olduğu için daha çok XML formatında dosya gönderiliyor. Dosya olarak göndermek mümkün olmadığı için XML dosyanın tamamı bir string değişken içine kaydedilerek iletiliyor.
Kod her ne kadar uzun gibi gözükse de aslında özünde basit. Birçok noktada hata kontrolü gerektiği için ve açıklama satırlarından dolayı normalden uzun oluyor. Server tarafında bilgisayar başında normalde bir kullanıcı bulunmuyor. Hata mesajlarını karşı tarafa özellikle iletmek gerekiyor ki bir sorun çıktığında ne olduğunu tespit etmek daha kolay olsun.
Kod her ne kadar uzun gibi gözükse de aslında özünde basit. Birçok noktada hata kontrolü gerektiği için ve açıklama satırlarından dolayı normalden uzun oluyor. Server tarafında bilgisayar başında normalde bir kullanıcı bulunmuyor. Hata mesajlarını karşı tarafa özellikle iletmek gerekiyor ki bir sorun çıktığında ne olduğunu tespit etmek daha kolay olsun.
Kod: Tümünü seç
{ Invokable implementation File for TDeneme which implements IDeneme }
unit DenemeImpl;
interface
// Aşağıdaki "uses" ile başlayan satır zaten File-New-Other-WebServices-SOAP Server Application seçeneği ile otomatik oluşturuluyor.
// Ekstra eklenen unitelerin açıklamaları mevcut
// Ben Interface adına "Deneme" dedim. Otomatik olarak DenemeIntf.pas ve DenemeImpl.pas dosyaları oluşturuldu.
// Bu dosya DenemeImpl.pas dosyasıdır.
uses Soap.InvokeRegistry, System.Types, Soap.XSBuiltIns, DenemeIntf,
System.SysUtils, // StrPCopy için kullanılıyor
Uni, // Uni TUniQuery için kullanılıyor
DataSnap.Provider, // TDataProvider için kullanılıyor
DataSnap.DBClient, // TClientDataSet için kullanılıyor
Windows; // GetTempFileName için kullanılıyor
type
{ TDeneme }
TDeneme = class(TInvokableClass, IDeneme)
public
function echoEnum(const Value: TEnumTest): TEnumTest; stdcall;
function echoDoubleArray(const Value: TDoubleArray): TDoubleArray; stdcall;
function echoMyEmployee(const Value: TMyEmployee): TMyEmployee; stdcall;
function echoDouble(const Value: Double): Double; stdcall;
function Adresler: string; stdcall; // Tablo içeriğini göndermek için kullandığım fonksiyon.
// Bu fonksiyon ayrıca "DenemeIntf.pas" dosyasına da "IDeneme" interface içine bu fonksiyon manuel eklenmeli.
end;
implementation
uses uData; // uData = TDM oluyor. İçinde database bağlantısını yapan TUniConnection var.
// [...] Aradaki otomatik oluşturulan fonksiyonları buraya kopyalamadım. Sadece kendi eklediğ fonksiyonu gösteriyorum.
function TDeneme.Adresler: string; stdcall;
var
LProvider : TDataSetProvider; // Query sonucunu TClientDataSet içine doldurmada aracılık yapıyor
LClient : TClientDataSet; // Query sonucu bu nesne içine dolduruluyor.
q : TUniQuery; // Bunun yerine AdoQuery veya AdoTable vs. kullanılabilir. Ben UniDAC kullanmayı tercih ediyorum.
F:TextFile; // XML dosyasını diskten okuyup string değişkene aktarmak için
s:string;
lpTempFileName: Array[0..MAX_PATH] of char; // GetTempFileName için
begin
// Aynı anda birden fazla bağlantı talebi gelirse diye fonksiyon içinde yeni nesne oluşturuluyor.
q := TUniQuery.Create(nil);
try
q.Connection := DM.UniConnection1;
q.SQL.Add('select * from ADRES');
try
q.Prepare;
q.Open;
// Yine birden çok bağlantı gelirse diye kod ile nesne oluşturuluyor.
LProvider:=TDataSetProvider.Create(nil);
try
LProvider.DataSet := q;
// Yine birden çok bağlantı gelirse diye kod ile nesne oluşturuluyor.
LClient:=TClientDataSet.Create(nil);
try
LClient.SetProvider(LProvider);
LClient.Active:=True;
try
// Geçici dosya adı al.
// Bu dosya diskte 0 byte uzunluğunda oluşturulur.
// Aşağıdaki LClient.SaveToFile prosedürü dosya varsa üzerine yazacağı için sorun yok.
GetTempFileName('.', nil, 0, lpTempFileName);
s := lpTempFileName;
Delete(s, 1, 2); // ".\"
// s değişkeni başka amaçlar içinde kullanılıyor.
// Dosya adının son halini orjinal değişken içinde sakla
StrPCopy(lpTempFileName, s);
except
// Kullanıcının Temp dizinine veya EXE dosyanın bulunduğu dizine yazma yetkisi yok
s := EmptyStr;
// Hata oluştur ki karşı tarafa da (WebServisi consume eden tarafa) sorun olduğu bildirilmiş olsun.
raise;
end;
// Query sonucunu XML dosyası olarak sakla
LClient.SaveToFile(s, dfXMLUTF8);
finally
LClient.Free;
end;
finally
LProvider.Free;
end;
except
// Query çalıştırılamadı.
on E:Exception do begin
raise Exception.Create('Query çalıştırılamadı. Orjinal hata mesajı:' + E.Message);
end;
end;
// XML dosyasını direk değişken içine alamadığım için önce diske kaydediyorum
// Sonra diskten değişken içine okuyorum.
if s <> EmptyStr then begin
if FileExists(s) then begin
AssignFile(F, s);
try
Reset(F);
Result := EmptyStr; // Result değişkeni string cinsinden. Maksimum 2GB kapasitesi var.
while not Eof(F) do begin
ReadLn(F, s);
Result := Result + s;
end;
CloseFile(F); // Dosyayı kapatmayı unutma
// Geçici dosyayı silmeyi unutma
if not DeleteFile(lpTempFileName) then begin
// Kod buraya kadar geldi ise geçici dosyayı diskte oluşturabildik demektir.
// Dolayısıyla silme ile ilgili sorun yaşamamamız lazım.
// Eğer geçici dosya silinemez ise yığınla dosya birikir.
// GetTempFileName bir sonraki çalışmada geçici dosya adı bulmakta zorlanır.
// Windows dizin içeriğini okumada yavaşlar.
// vs. vs. vs.
// Dolayısıyla hata mesajı çevir.
raise Exception.Create('Geçici dosya silinemiyor. Dosya adı:' + lpTempFileName);
end;
except
on E:Exception do begin
raise Exception.Create('Geçici dosya okunamıyor. Dosya Adı:' + lpTempFileName + #13 + 'Orjinal hata mesajı:' + E.Message);
end;
end;
end else begin
raise Exception.Create('Geçici dosya bulunamıyor. Dosya adı:' + s);
end;
end else begin
raise Exception.Create('s değişkeni boş. İçinde geçici dosya adı olması gerekiyordu');
end;
finally
q.Free; // Nesneyi manuel oluşturunca manuel Free etmek gerekiyor
end;
end;
Re: Web Servis - sunucudan dataset göndermek
İsterseniz diske kaydetmeden de doğrudan,SaveToStream methodu ile veriyi TMemoryStream'a aktarıp ordan da okuyabilirsiniz.ertank yazdı:Kod: Tümünü seç
LClient.SaveToFile(s, dfXMLUTF8);