====================================
conversion routines
====================================
Format('There are now %d records in the table %s', [10,'TableA']); -->格式化字元串
function Now(): TDateTime; --> 傳回目前的日期和時間, DateTime類型(其實就是double型)
function Date(): TDateTime; --> Returns the current date.
function CompareDateTime(const A, B: TDateTime): int; -->比較2個日期
function EncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word):
TDateTime; -->拼日期
procedure DecodeDateTime(const AValue: TDateTime; out AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word);
ExtractFilePath(Application.ExeName) -->擷取目前程式路徑
//簡單類型轉換
function IntToStr(Value: Integer): string;
function FloatToStr(Value: Extended): string;
Format('%d%s',[100,'hello'])
procedure DateTimeToString(var Result: string; const Format: string; DateTime: TDateTime);
function FormatDateTime(const Format: string; DateTime: TDateTime): string;
格式'yyyymmddhhnnsszzz' 是精确到毫秒的格式
FormatDateTime()和DateTimeToString() 都能很好将日期格式化成String, 但沒有那種根據格式解析DateTime的函數, 需要自己寫, 或者找開源的rx_library庫
//char和string的轉換
Char=>String: StringOfChar(char1, 1), 或者 char1+''即可
String=>Char: String使用下标即可轉成Char, 比如String123[0]
//PChar和String的互換
String=>PChar
最好使用 PChar('your_string') 強轉; 使用StrPCopy(Dest: PChar; const Source: string), 它有時會報記憶體錯誤.
function StrPas(const Str: PChar): string;
Converts null-terminated string to an AnsiString (long string)
====================================
how to use Win32 system functions
====================================
function GetTempPath1: string;
var
TempDir: array[0..255] of Char;
//DWORD GetTempPath(DWORD nBufferLength, LPTSTR lpBuffer);
begin
GetTempPath(255, @TempDir);
Result := StrPas(TempDir);
end;
====================================
refresh FORM appearance in a busy loop
====================================
procedure TMainForm.Btn_Stress_Test_LoopClick(Sender: TObject);
var
I: Integer;
begin
for I := 0 to StrToInt(edt_total_count.Text) do
begin
edt_current_index.Text:=IntToStr(I);
self.stressTest();
Application.ProcessMessages();
end;
end;
====================================
解決DCOM中間層報錯問題, 報錯資訊是: Name not unique in this context
====================================
這是一個基于DCOM技術開發的老程式, 包含中間層和用戶端, 中間層使用MultiInstance 程序 + Apartment 線程模型, 有一個Remote data module通過BDE技術連接配接Oracle.
當多個用戶端同時連中間層時, 經常能碰到報錯: Name not unique in this context.
原因分析: MultiInstance 程序模式的中間層, 也就是一個程序服務所有的RPC調用. 當有多個RPC進來的時候, 啟用多線程方式進行服務. 是以需要中間層有一個session管理機制. 預設情況下, BDE中間層僅僅有一個default session, 一旦多個用戶端同時連着并作查詢, 程式會在同一個session中, 建立資料結果集或其他對象, 就會報"Name not unique in this context."錯誤.
解決方法是:
首先:Remote data model上, 加 Session1(TSession 元件), 設定AutoSessionName=True, 假設 SessionName為Session1_2 .
接着:確定DBE TDatabase 元件SessionName為Session1的SessionName, 即Session1_2
最後:為Session1 設定PrivateDir. 確定每個連上中間層的session都有一個唯一的PrivateDir, 否則還會報 Directory is busy 錯誤. 我的做法是在Session1Startup事件中, 為session1動态指定一個臨時目錄.
測試的政策:
要模拟多個用戶端'同時'連接配接中間層, 需要有點政策. 我的做法是: 随便找一個查詢, 循環100次封裝成一個方法. 然後啟動3份用戶端程式, 同時運作這個新的循環程式. 因為有100次循環, 是以必然會有多個用戶端同時連接配接中間層.
增加 TSession 元件,
object Session1: TSession
AutoSessionName = True
KeepConnections = False
PrivateDir = ' '
OnStartup = Session1Startup
SessionName= 'Session1_2'
Left = 32
Top = 104
end
確定DBE TDatabase 元件SessionName為Session1的SessionName, 不是Session1的元件名字.
object your_db: TDatabase
AliasName = 'your_db'
DatabaseName = 'your_db'
KeepConnection = False
LoginPrompt = False
Params.Strings = (
'user name=user1'
'password=pwd')
SessionName = 'Session1_2'
Left = 24
Top = 48
end
procedure TApp.Session1Startup(Sender: TObject);
var
TempDir: array[0..255] of Char;
tempPath:String ;
fullPrivatePath:String;
begin
// set private dir for this new session
GetTempPath(255, @TempDir);
tempPath:= StrPas(TempDir);
fullPrivatePath:=tempPath+guid_str(); //使用guid來保證目錄的唯一性
CreateDirectory(PChar(fullPrivatePath),nil);
Session1.PrivateDir:= fullPrivatePath;
end;