顯示具有 ADO 標籤的文章。 顯示所有文章
顯示具有 ADO 標籤的文章。 顯示所有文章

2019/07/18

ADO in Web application for Delphi


主題雖然說是 ADO,其實泛指利用操作COM*的資料庫 Driver 皆適用,例如:使用到 OleDB / SQL Native Client 的 dbExpress、Devart DAC、FireDAC 元件等。

*元件物件模型英語:Component Object Model,縮寫COM

Delphi 在 Web Application 開發會使用到 Thread,所以使用 COM 技術時,必須要使用 CoInitialize / CoUninitialize 來避免存取錯誤。

使用時機通常是伴隨著 Method 開始和結束,例如:

procedure Method;
begin
  CoInitialize(nil);
  ...
  CoUninitialize;
end;

每一個 Method 要設定也太累人,總是想找個簡易的作法,運氣不錯,一找就看到有意思的作法,高手連結在此

WebModule的【BeforeDispatch】和【AfterDispatch】事件主要控制 Method (Action) 的起始和結束,所以我們可以分別加入 CoInitialize 和 CoUnitialize,如此一來便可以少寫很多的程式碼。

文中的 CGI 模式也可以套用到 Windows Service 專案中,真是長知識了!


See also:

2019/06/11

Delphi 操作 AD / LDAP 的相關資源



以往登入介面會想使用在資料庫建立使用者清單,但老是會被提到不要讓使用者多記一組密碼。

而大多數的企業內都是使用 Active Directory 管理登入,能夠使用 AD 驗證登入資訊當然是最佳解。

Google 搜尋後驚覺有提到 AD 的都是 C# 內容,Delphi 相關的很少很少。

不過呢,在有限的資料中卻發現:Delphi 和 Active Directory (AD / LDAP) 也蠻合的,而且 ADOQuery 居然還能查 AD 資料,ADO 也太威能了吧!

2020.02.05補充:

執行時的 Access EViolation

由於LDAP filter 會用到冒號【:】,這是Delphi SQL 參數的保留字,若沒有關閉ParamCheck會造成參數存取錯誤(Access Violation)的情形。

SQL Like 語法調整

雖然LDAP可以用類SQL語法查詢,畢竟不是SQL-92標準,如LIKE語法沒有提供,取而代之的是使用米字符號【*】表示。

See also :


2012/12/14

幾種提昇 MDAC 應用程式效能的方法

資料來源:http://www.reocities.com/huanlin_tsai/faq/n012.txt

1.在記錄的迴圈當中使用預先連結的欄位物件

  參考下面的範例:

  procedure TForm1.Button1Click(Sender: TObject);
  var
    fldID, fldName, fldAge: TField;
  begin
    fldID := ADODataSet1.FieldByName('ID');
    fldName := ADODataSet1.FieldByName('Name');
    fldAge := ADODataSet1.FieldByName('Age');
    ADODataSet1.First;
    while not ADODataSet1.Eof do
    begin
      writeln(fldID.AsString);
      writeln(fldName.AsString);
      writeln(fldAge.AsString);
      ADODataSet1.Next;
    end;
    ADODataSet1.Close;
  end;

2.除非必要,否則不要使用 cursor-based 的方式更新資料

  雖然使用 SQL 命令來更新資料在某些情況下並不適合,你還是應該盡量
  使用這種方式,經由 recordset 物件 (TADODataSet 及其後代) 來更新
  資料雖然方便,但所必須付出的代價也較大,儘管 SQL 命令比較難以使
  用,但是絕對值得。

3.使用帶輸出參數的預儲程序取代只傳回一筆記錄的 Select 敘述

  當你知道 query 傳回的結果集只有一筆記錄時,你可以使用帶輸出參數
  的預儲程序取代開啟一個 recordset。
  當你開啟一個 recordset 時,傳回的結果集包含了資料以及 metadata
  ,通常 metadata 的資料量蠻大的,所以你可能會想用一個帶輸出參數
  的預儲程序。

  Sub SingletonSp()

    Dim cmd As New Command
   
    cmd.ActiveConnection =
      "Provider=SQLOLEDB;DataSource=sureshk1;Database=pubs;" & _
      "User Id=sa;Password=;"
   
    cmd.CommandText = "GetAuthorName"
    cmd.CommandType = adCmdStoredProc
   
    cmd.Parameters.Append cmd.CreateParameter(
      "Id", adChar, adParamInput, 11)
    cmd.Parameters.Append cmd.CreateParameter(
      "FName", adChar, adParamOutput, 30)
    cmd.Parameters.Append cmd.CreateParameter(
      "LName", adChar, adParamOutput, 30)
   
    cmd(0) = "172-32-1176"
    cmd.Execute
    Debug.Print cmd(1), cmd(2)

  End Sub

  Sub SingletonSelect()

    Dim rs As New Recordset
   
    rs.ActiveConnection =
      "Provider=SQLOLEDB;Data Source=sureshk1;Database=pubs;" & _
      "User Id=sa;Password=;"
    rs.Source = "select au_fname, au_lname from authors where" & _
      " au_id = '172-32-1176'"
    rs.Open
   
    Debug.Print rs!au_fname, rs!au_lname

End Sub


4.如果你必須使用 cursor,對傳回一筆記錄的結果集使用 Collect 方法

  Recordset::get_Collect 及 Recordset::set_Collect 方法可以讓你
  不用透過欄位物件而快速的存取欄位值,這種方法最適合用在只傳回一
  筆記錄的結果集。

  Sub Collect()

    Dim rs As New Recordset
   
    rs.ActiveConnection =
      "Provider=SQLOLEDB;Data Source=sureshk1;Database=pubs;" & _
      "User Id=sa;Password=;"
    rs.Source = "select au_id, au_fname, au_lname from authors" & _
      " where au_lname = 'Green'"
    rs.Open
   
    Debug.Print rs.Collect(0), rs.Collect(1), rs.Collect(2)
    ' VBA shortcut
    Debug.Print rs!au_id, rs!au_fname, rs!au_lname

  End Sub

5.只取得你所要的資料

  Select * 的簡單使用容易讓人養成壞習慣,考慮只將你要的欄位 select
  進來,同時也要考慮用 where 來限制傳回的記錄數量。

6.小心選擇你的 cursor location

  如果你不需要捲動或者更新記錄,就使用 ADO 的內定值:
    CursorLocation = adUseServer
    CursorType = adOpenForwardOnly
    LockType = adLockReadOnly
  此內定值讓你最快速的存取只能向前捲動的結果集。
  把握一個原則: 根據需求做適當的設定,不要給多餘而不必要的功能。

  如果你需要前後移動記錄,就不要使用 adUseServer,ADO 將
  adUserServer 做為內定值是由於向後相容的考量。在大部分需要捲動
  的情況下,使用 client cursor 會比較適當,只有在比較特殊的情況
  下,像是資料量非常龐大的時候,就應該使用 server cursor。
  另外,如果你使用 client cursor,但是並不需要更新資料時,請將
  LockType 設定為 adLockReadOnly,如果你需要更新資料,client
  cursor 引擎必須取得額外的 metadata,而這會付出昂貴的代價。

  後端為 SQL Server 時應避免使用 Static 及 Keyset cursor,SQL
  Server 並不直接支援 Static 及 Keyset cursor,它必須複製資料到
  暫存資料表,因此降低了效能。

  註1:當 CursorLocation 為 adUseClient 時,ADO 會自動將 CursorType
      設定為 adOpenStatic,即使你設定成其他值,在開啟資料集時 ADO
      就會自動改為 adOpenStatic。
  註2:Microsoft Jet database engine 不支援 dynamic cursor,所以OLE
      DB Provider for Microsoft Jet 不支援 adLockDynamic cursor。
  註3:當 CursorType 為 adOpenForwardOnly 或 adOpenDynamic 時,
      Recordset 的 RecordCount 屬性總是等於-1。參考 http://
      support.microsoft.com/support/kb/articles/q194/9/73.asp

7.調整 Recordset 的 CacheSize 屬性 (TADODataSet.CacheSize)

  ADO 使用 Recordset 的 CacheSize 來決定要快取的記錄數量,當你在
  快取的記錄範圍內移動 cursor 時,ADO 會直接由快取中傳回資料,當
  你移出快取範圍時,ADO 會釋放快取,並且取得下一批快取記錄。
  那麼 CacheSize 要設定多少會有最佳效能呢? 答案是視情況而定。你
  應當嘗試用多個不同的 CacheSize 來找出讓你的應用程式表現最佳的
  設定值(建議值: 10)。

8.儘快釋放掉沒有使用的 ADO 物件

9.自行描述命令參數

  即 Delphi ADOExpress 的 TADOCommand.Parameters 屬性, 例如:

    with ADOCommand1.Parameters do
    begin
      Items[0].Name := 'ReturnValue';
      Items[0].DataType := ftInteger;
      Items[0].Direction := pdReturnValue;
    end;

10.使用原生 OLE DB Providers 

11.對唯讀資料集以及需要較長時間的處理可以切斷 client cursor 與
   connection 的連結以增進效能

   切斷 Recordset 連結是 client cursor 引擎的一項功能,當你在處
   理較費時的工作時可以利用這項功能,處理完之後可以再恢復連結。
   Delphi 的 TADODataSet 及其後代應該只要將 Connection 屬性設為
   nil 即可 (未驗證)。

12.不需要傳回結果集時使用 Connection 的 adExecuteNoRecords 選項

  當你使用這個選項時,ADO 不會建立 Recordset 物件,也不會設定任
  何 cursor 屬性。

  Delphi:

    TADOConnection.Execute(CommandText, eoExecuteNoRecords);

13.對於只使用一次的命令使用 Connection::Execute

  當你使用 Connection::Execute 方法執行只需一次的命令時,ADO 對
  此做了些效能最佳化。常見的使用時機是用在 IIS, ASP, 及 MTS 環境
  下,典型的步驟是: 開啟 connection,執行傳回或不傳回資料集的命
  令,處理結果集,然後關閉 connection。在這種情況下應該使用
  Connection::Execute 以取代 Recordset::Open 或 Command::Execute
  。當你使用 Connection::Execute 方法時,ADO 不會保留任何命令的
  狀態資訊,因此會獲得較好的效能。如果你需要較多功能的 cursor 或
  者你需要再執行 Execute 方法時帶參數的話,你仍然需要使用
  Recordset::Open 或 Command::Execute 方法。



參考文件

  http://www.microsoft.com/data/impperf.htm
  http://vbdata.iwarp.com/speed.htm

2012/11/27

Delphi 的 ActiveX Form 相關筆記(未整理)






Delphi7 BUG Web Deployment Options呈灰色的解决

这是d7的bug,处理方法很简单

每次打开工程后,新建一个ActiveForm页,然后再从工程中删除,再到type   library中删掉相应的内容就可以使用deploy了。 

另一个解决办法,你可以打开".DOF"文件进行手工修改下面单元:

[Deployment]
DeployDir=d:\
DeployURL=d:\
HTMLDir=d:\
CABCompress=0
CodeSign=0
IncludeVerInfo=1
AutoIncRelease=0
DeployPackages=1
DeployFiles=0
CompanyURL=
Description=
CredFile=
PrivKey=
CryptoType=0
Timestamping=0
TimestampServer=

2012/05/29

Variant function: VarIsEmpty VS VarIsNULL

unassined :
if Not VarIsEmpty( DeltaDs.Fields[i].NewValue ) then ...

NULL :
if Not VarIsNULL( DeltaDs.Fields[i].NewValue ) then ...

資料來源:http://www.sql.ru/forum/actualthread.aspx?tid=329100

2012/05/07

2012/03/31

Use Thread to open ADO


type
  TOpenQuery = Class(TThread)
  Public
     constructor Create(Q: TADOQuery;sSQL: String);
  protected
     tQry: TADOQuery;
     tSQL: String;
     procedure Execute; override;
  end;

{ TOpenQuery }

constructor TOpenQuery.Create(Q: TADOQuery; sSQL: String);
begin
  inherited Create(False);

  FreeOnTerminate:=True;
  tQry:=Q;
  tSQL:=sSQL;
end;

procedure TOpenQuery.Execute;
begin
  inherited;

  Screen.Cursor:=crAppStart;
  with tQry do Begin
     SQL.Text:=tSQL;
     Open;
  End;

  Screen.Cursor:=crDefault;
end;