Konuyu Oyla:
  • Derecelendirme: 0/5 - 0 oy
  • 1
  • 2
  • 3
  • 4
  • 5
MSSQL TableType tipinde parametre nasıl geçilir?
#21
Tekrar merhaba,


10.3 de standart bileşenlerle örnek bir proje yaptım.
Kısaca anlatmak gerekirse,
2 connection var. biri kaynak diğeri hedef sunucu.ancak örnekte herikiside aynı sunucuya bağlanıyor .
açılışta bağlandığın kaynak sunucu ve veritabanına  bir tablo oluşturup içerisine 5 satır veri ekliyor.
table tipli veri tipi oluşturuyor,
ve son olarak bu table tipli veri tipi ile bir prosedür yaptım , input alıyor ve sonra select ediyor.
A kaynak sunucusundaki adodatasetteki veriyi döngü ile alıp Table Value Constructor  tipine çevirip üstüne ve altına gerekli ilaveleri yapıp diğer sunucun prosedürüne table tipli veri tipine gönderiyor prosedür de bu gelen tabloyu select ediyor örnekte.
oluşan kodu ve diğer çalıştırdığı tüm kodlarıda  memoya aktarıyorum oradan da inceleyebilirsin oluşan kodu.

https://www.dosya.tc/server35/fmj1me/TEMP.rar.html
not:uses da globdb üniti kalmış, kaldırabilirsiniz kullanılmıyor.

görselde üstteki data tablodan direk select edilen veri,
alttaki data adodan döngü ile alınıp Table Value Constructor  tipine çevirip üstüne ve altına gerekli ilaveleri yapıp diğer sunucun prosedürünün çalışmış sonucu
   

datadan oluşan Table Value Constructor   string

   
İmkanın sınırı, imkansızın yanıbaşındadır. Denemeden bilemezsin.
Cevapla
#22
@bydelphi
Linkini verdiğiniz örnek dosya RAR ile paketlenirken yanlışlıkla şifrelemiş olabilir misiniz ?
Saygılarımla
Muharrem ARMAN

guplouajuixjzfm15eqb.gif
Cevapla
#23
Shocked 
(25-12-2021, Saat: 22:41)mrmarman Adlı Kullanıcıdan Alıntı: @bydelphi
Linkini verdiğiniz örnek dosya RAR ile paketlenirken yanlışlıkla şifrelemiş olabilir misiniz ?

Çok özür Sad
şifre 1071  yazmayı unutmuşum.
İmkanın sınırı, imkansızın yanıbaşındadır. Denemeden bilemezsin.
Cevapla
#24
@bydelphi
Uğraşlarınız için teşekkür ederim.
Çok emek harcamışsınız elinize sağlık sağolun varolun.
Fakat örneğinizi incelediğimde parametre geçişi ben hala göremedim.
Yaptığınız örnek ExecSQL işlemi TableType sınıfında bir geçişi benmi göremedim acaba
Belkide yazdığınız kodu ben yanlış yorumlamışta olabilirim.

@mrmarman Hocamın verdiği linkte çalışan örnek benzeri bir yapı olmuş sanırım
Değerli Üstad ve hocalarımız bu konuyu benden daha iyi değerlendireceklerdir eminim.
Bu dünyada kendine sakladığın bilgi ahirette işine yaramaz. 
Cevapla
#25
(26-12-2021, Saat: 23:38)adelphiforumz Adlı Kullanıcıdan Alıntı: @bydelphi
Uğraşlarınız için teşekkür ederim.
Çok emek harcamışsınız elinize sağlık sağolun varolun.
Fakat örneğinizi incelediğimde parametre geçişi ben hala göremedim.
Yaptığınız örnek ExecSQL işlemi TableType sınıfında bir geçişi benmi göremedim acaba
Belkide yazdığınız kodu ben yanlış yorumlamışta olabilirim.

@mrmarman Hocamın verdiği linkte çalışan örnek benzeri bir yapı olmuş sanırım
Değerli Üstad ve hocalarımız bu konuyu benden daha iyi değerlendireceklerdir eminim.

Aslında parametre var hemde tam senin istediğin table tipli input parametre prosedürün içerisinde ona veri gönderiyoruz.
Memo3 ü incelersen daha net görürsün. lines dan girip tüm texte bak, scrollbar kapalı tam görünmüyor .
@ VAL ın içerisinde senin milyonluk datan var datasetten while ile dönen.
alttaki kodla memo3 deki  uzaksunucuda çalışacak olan procedure sqle bu parametre geçiliyor.
   QrServerB.Close;
  QrServerB.SQL.Text :=
  StringReplace(Memo3.Text,'[@VAL]',Memo2.Text,[rfReplaceAll]);
  QrServerB.Open;
İmkanın sınırı, imkansızın yanıbaşındadır. Denemeden bilemezsin.
Cevapla
#26
(26-12-2021, Saat: 23:38)adelphiforumz Adlı Kullanıcıdan Alıntı: @bydelphi
Uğraşlarınız için teşekkür ederim.
Çok emek harcamışsınız elinize sağlık sağolun varolun.
Fakat örneğinizi incelediğimde parametre geçişi ben hala göremedim.
Yaptığınız örnek ExecSQL işlemi TableType sınıfında bir geçişi benmi göremedim acaba
Belkide yazdığınız kodu ben yanlış yorumlamışta olabilirim.

@mrmarman Hocamın verdiği linkte çalışan örnek benzeri bir yapı olmuş sanırım
Değerli Üstad ve hocalarımız bu konuyu benden daha iyi değerlendireceklerdir eminim.

Exec ql dediğimiz bölüme senin ihtiyacın zaten yok, sisitemi örnek için kotrol edip hazırlıyor. 
test için tablo , tablo için veri , ve veriyi taşımak içinde bir adet table tipi veri tipi oluşturuyor.
bunu da zaten kotrol ederek sadece bir kere oluşturuyor hata vermemek için 
yani sistemi örnek için hazırlıyoruz. 

senin asıl işin butona basınca döngü ile dönüp recordseti texte dönüştürüp  sonucu memoya alıp [@ val] ile prosedür table tipli değişkenine göndermek yani buton içeirisi. orayı incele
İmkanın sınırı, imkansızın yanıbaşındadır. Denemeden bilemezsin.
Cevapla
#27
Bugün izin günüm. 

* Ne yapsam dedim sizin için bir test hazırladım.
* İlk defa SQLServer'a böyle bir formül ile erişim yaptım. Microsoft'a ne kadar kızsak da kaynak çok.

Arrow Arrow Arrow Sizin örnek tablo adı ile yürüdüm. Lütfen dikkatli olalım, içerisinde Arrow "DELETE FROM"  Arrow  içeren SQL tüm tabloyu silecektir. kayıt sayısı içerikli TEST sağlığı açısından boş tabloda çalışmak iyidir. Gerekli yedekler vs. alınarak başlayınız veya başka bir tablo üretip onunla denemelerinizi yapınız..


Aşağıdaki örnek BATCH olarak yerelde onlarca kaydı biriktirip topluca sunucuya aktarmak üzere bir örnektir.
Showmessage ile duraklamaları sizin gözle kontrol edebilmeniz için ekledim. aTestCount kadar kaydı yerelde çok hızlı bir şekilde biriktirecektir. Bunu START ve FINISH showmessage satırlarının geçiş hızı ile gözlemleyebilirsiniz.

Asıl burada test edeceğiniz unsur, iki tane "Server WAIT TEST" arasındaki süre. Bu süre BATCH içinde biriken aTestCount tane kaydın uzak sunucuya aktarım süresidir. Kanımca C# ile elde edilen süreyi yakalayacaksınız.  

Eklediğim görselde 1000 record için deneme yaptım. Hem WiFi kalitemin düşüklüğü hem sanal makineden Network Bridge ile yavaşlık hem de VPN üzerinden SQLServer ağına bağlı olmam nedeniyle görece biraz yavaş kaldı ama eminim ki normal bir network'de tek tek kayıt girmekten çok çok hızlı olacaktır. Çünkü batch demek yığın demek. ADO da bunu hangi dil olursa olsun (delphi, C#, vs. ) aynı teknikle yapıyor olmalı.

Uses
DB, AdoDB, ADOInt,
ComObj, DateUtils;

const
 // ------ SQL Server & Master Account ------  //
 FCatalog          = '<CatalogDatabase>';
 FServer_Adr       = '<ServerIp>';
 FServer_Port      = '1433';
 FMaster_UserID    = '<UserLogin>';
 FMaster_Password  = '<UserPass>';


Const
 xMSSQL = 'Provider=SQLOLEDB.1;'
         +'Persist Security Info=True;'
         +'Data Source=%s,%s;'
         +'Initial Catalog=%s;'
         +'User ID=%s;'
         +'Password=%s;'
         +'Trusted_Connection=true;'
         ;

procedure TestRecords( aTestCount: Integer );
var
 LConnection : OleVariant;
 LRecordSet  : OleVariant;
 LFields     : OleVariant;
 LValues     : OleVariant;

 LRecCount   : Integer;
 i           : Integer;
begin
 LConnection := CreateOleObject('ADODB.Connection'); // veya TADOConnection.ConnectionObject
 LRecordset  := CreateOleObject('ADODB.RecordSet');
 try
   LConnection.Mode := adModeReadWrite;
   LConnection.Open( Format( xMSSQL, [ FServer_Adr, FServer_Port, FCatalog, FMaster_UserID, FMaster_Password ]) );

   LRecordSet.CursorLocation := adUseClientBatch;  //  anahtardaki "Batch" kaldırılırsa direkt kayıt yapar
   LRecordSet.CursorType     := adOpenDynamic;
   LRecordSet.LockType       := adLockBatchOptimistic;   // anahtardaki "Batch" kaldırılırsa direkt kayıt yapar

 //!!DİKKAT!!  Empty Table...
   LConnection.Execute( 'DELETE FROM [API_ERP_CariBakiyeTable]' );

   LRecordset.Open( 'SELECT * FROM [API_ERP_CariBakiyeTable]', LConnection, adOpenDynamic, adLockBatchOptimistic, 0 ); // anahtardaki "Batch" kaldırılırsa direkt kayıt yapar
   LRecCount := LRecordset.RecordCount;

   if LRecCount > 0
     then ShowmessageFmt( 'RecordCount = %d', [LRecCount] );

   LFields := VarArrayOf([ 'IslemTipi',  'LogicalRef',     'Code', 'Definition',
                            'AlacakBakiye', 'BorcBakiye', 'SonBorcTarihi',  'SonAlacakTarihi' ]);
   LValues := VarArrayOf([ 'S', 1, '1234567', 'Def Sample', 1.5, 2.5,
                            now(), IncDay(now(), 7) ]); // 2021-12-28 10:18:45.000

ShowMessage('Start Batch Record');
   for i := 1 to aTestCount do
   begin
     LRecordSet.AddNew( LFields, LValues );
   end;
ShowMessage('Finish Batch');

Showmessage('Server WAIT TEST: Before Update TEST Table');
   LRecordSet.UpdateBatch;
showmessage('Server WAIT TEST: After  Update TEST Table');

 finally
   LConnection.Close;
   LConnection := UnAssigned;
   LRecordset  := UnAssigned;
 end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 TestRecords( 1000 );
end;



Çalışmalarınızda başarılar.







frlgtfj2oj29lnh9lsr3.gif
Saygılarımla
Muharrem ARMAN

guplouajuixjzfm15eqb.gif
Cevapla
#28
@mrmarman Hocam
Zaman ayırıp böyle bir çalışmaya katkı sağladığınız için teşekkür ederim.
Bu dünyada kendine sakladığın bilgi ahirette işine yaramaz. 
Cevapla
#29
@adelphiforumz bu arada benim için de oldukça eğitici bir soru oldu. Seni daha iyi anladım.

Hakikaten DotNet olmayan platformdan SQLServer'a olan bu yaklaşımdaki sıkıntıyı buradaki örnek ile kolları sıvayınca gördüm.
Sonradan _Recordset'i XML'ye dönüştürüp bunu StoredProc içine parametre olarak yollayıp, StoredProc yakasında XML'yi table yapıp veritabanına basınca normal çalıştı. Yani atlar ve katırlar ile yola devam edince oluyor.  Smile


Şöyle ki, denemelerimde
  • Önce kendim sıfırdan ADO'nun delphi içerisinden "_Recordset" oluşturdum, oraya 1 tane kayıt girip yolladım olmadı.
  • Sonra "_Recordset" olmasın OleVariant tipinde ADO'nun sistemden okuduğu şekilde "_Recordset"', OleVariant dönüştürdüm olmadı. ( dotnet de bunu yapıyor o bakımdan )
  • Sonra hadi direkt OleVariant "ADODB.Recordset" oluşturup içine koydum yine olmadı.
  • Son olarak sunucuya bir kaç kayıt girdim. Bunu oradan okudum, sonra gerisin geriye sunucuya geldiği gibi / olduğu gibi bastım yine kabul etmedi.
Hep aşağıdaki hata ile karşılık veri. Sanki record içeriği yer ve / veya tip uyuşmazlığı var. Onun için record tiplerini sadeleştirip (sadece iki Integer veri tipi ile) denedim ki çaprazlanmış olsun. Yine aynı hata. 


jblvcyabnvudhbgiwinj.png

Bu arada merak edenler için yazayım, recordset sağlıklı mı ? belki de @mrmarman bunu doğru kuramadı derseniz diye, basit bir döngü ile bunu okuyup her defasında teyit ettim ve MoveToFirst ile ilk kayda döndüm - stream position (0) misali -

aşağıdaki teyit örneğinde hem LRecordSet hem de LLRecSet aynı şekilde içi dolu halde olduğu basit bir WHILE döngü ile kontrol edilebiliyor.


var
 LRecordSet  : OleVariant;
 LLRecSet    : _Recordset;
...
begin
 LRecordset  := CreateOleObject('ADODB.RecordSet');
 LConnection := CreateOleObject('ADODB.Connection'); // veya TADOConnection.ConnectionObject
 LCommand    := CreateOleObject('ADODB.Command');
 try
   LConnection.Mode := adModeReadWrite;
   LConnection.Open( Format( xMSSQL, [ FServer_Adr, FServer_Port, FCatalog, FMaster_UserID, FMaster_Password ]) );
...
...

   LFields := VarArrayOf([ 'IslemTipi',  'LogicalRef', 'Code', 'Definition',
                            'AlacakBakiye', 'BorcBakiye', 'SonBorcTarihi',  'SonAlacakTarihi'  ]);
   LValues := VarArrayOf([ 'S', 1, '1234567', 'Def Sample', 1.5, 2.5, now(), IncDay(now(), 7) ]);

   for i := 1 to aTestCount do
   begin
     LRecordSet.AddNew( LFields, LValues );
   end;

...
...
   if NOT LRecordSet.EOF then
   begin
     i := 0;
     while NOT LRecordSet.EOF do
     begin
       Showmessage( LRecordSet.Fields[6].Value );
       inc(i);
       LRecordSet.MoveNext;
     end;
     ShowmessageFmt( 'RecordCount = %d', [ i ] );
     LRecordSet.MoveFirst;
   end;


   LCommand.CommandType      := adCmdStoredProc;
   LCommand.CommandText      := LProc; // 'API_ERP_CariBakiyeEkle'
   LCommand.Parameters.Refresh;

 //LLRecSet := IDispatch( LRecordSet ) as AdoDB._Recordset;
   LCommand.Parameters[1].Value := LRecordSet;
// veya Parameters.Refresh demeden yani paramtreyi biz oluşturursak
//  LCommand.Parameters.Append( LCommand.CreateParameter( '@CariBakiyeTable',      adEmpty,   adParamInput,  0,  LRecordSet ) );


   LCommand.Execute;
   i := LCommand.Parameters[2];
   Showmessagefmt('Rec Count = %d', [i]);

Saygılarımla
Muharrem ARMAN

guplouajuixjzfm15eqb.gif
Cevapla


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  Trew View yapısında olan veriden Root kaydına nasıl ulaşılır adelphiforumz 9 996 25-12-2023, Saat: 08:06
Son Yorum: adelphiforumz
  Tarihin ayın kaçıncı haftası olduğu nasıl bulunur (Çözüldü) adelphiforumz 3 620 19-10-2023, Saat: 12:27
Son Yorum: serdar
  MSSQL Data downgrade (Alt sürüme veri aktarma) işlemleri adelphiforumz 0 540 23-03-2023, Saat: 11:13
Son Yorum: adelphiforumz
  MSSQL eş zamanlı yazma ve okuma kontrolü (Çözüldü) adelphiforumz 5 2.053 31-12-2021, Saat: 13:04
Son Yorum: adelphiforumz
  MSSQl üzerinde çalışan bir sorgunun durumu hakkında bilgi almak. Bay_Y 5 2.146 21-09-2021, Saat: 11:26
Son Yorum: Bay_Y



Konuyu Okuyanlar: 1 Ziyaretçi