ORM:對象關係映射Object Relational Mapping,簡稱ORM,或O/RM,或O/R mapping),是一種程序技術,用於實現面向對象編程語言裏不同類型系統的數據之間的轉換 [1] 。從效果上說,它其實是創建了一個可在編程語言裏使用的--“虛擬對象數據庫”。
面向對象是從軟件工程基本原則(如耦合、聚合、封裝)的基礎上發展起來的,而關係數據庫則是從數學理論發展而來的,兩套理論存在顯著的區別。爲了解決這個不匹配的現象,對象關係映射技術應運而生。
對象關係映射(Object-Relational Mapping)提供了概念性的、易於理解的模型化數據的方法。ORM方法論基於三個核心原則: 簡單:以最基本的形式建模數據。 傳達性:數據庫結構被任何人都能理解的語言文檔化。 精確性:基於數據模型創建正確標準化的結構。 典型地,建模者通過收集來自那些熟悉應用程序但不熟練的數據建模者的人的信息開發信息模型。建模者必須能夠用非技術企業專家可以理解的術語在概念層次上與數據結構進行通訊。建模者也必須能以簡單的單元分析信息,對樣本數據進行處理。ORM專門被設計爲改進這種聯繫。
簡單的說:ORM相當於中繼數據。具體到產品上,例如ADO.NET Entity Framework。DLINQ中實體類的屬性[Table]就算是一種中繼數據。
SOA:面向服務的架構(SOA)是一個組件模型,它將應用程序的不同功能單元(稱爲服務)通過這些服務之間定義良好的接口和契約聯繫起來。接口是採用中立的方式進行定義的,它應該獨立於實現服務的硬件平臺、操作系統和編程語言。這使得構建在各種各樣的系統中的服務可以以一種統一和通用的方式進行交互。
耦合與內聚:相反概念,內聚標誌一個模塊內各個元素彼此結合的緊密程度,它是信息隱蔽和局部化概念的自然擴展。內聚是從功能角度來度量模塊內的聯繫,一個好的內聚模塊應當恰好做一件事。它描述的是模塊內的功能聯繫。耦合是軟件結構中各模塊之間相互連接的一種度量,耦合強弱取決於模塊間接口的複雜程度、進入或訪問一個模塊的點以及通過接口的數據。 程序講究的是低耦合,高內聚。就是同一個模塊內的各個元素之間要高度緊密,但是各個模塊之間的相互依存度卻要不那麼緊密。 [2]
內聚和耦合是密切相關的,同其他模塊存在高耦合的模塊意味着低內聚,而高內聚的模塊意味着該模塊同其他模塊之間是低耦合。在進行軟件設計時,應力爭做到高內聚,低耦合。
(1) 內容耦合。當一個模塊直接修改或操作另一個模塊的數據時,或一個模塊不通過正常入口而轉入另一個模塊時,這樣的耦合被稱爲內容耦合。內容耦合是最高程度的耦合,應該避免使用之。
(2) 公共耦合。兩個或兩個以上的模塊共同引用一個全局數據項,這種耦合被稱爲公共耦合。在具有大量公共耦合的結構中,確定究竟是哪個模塊給全局變量賦了一個特定的值是十分困難的。
(3) 外部耦合 。一組模塊都訪問同一全局簡單變量而不是同一全局數據結構,而且不是通過參數表傳遞該全局變量的信息,則稱之爲外部耦合。
(4) 控制耦合 。一個模塊通過接口向另一個模塊傳遞一個控制信號,接受信號的模塊根據信號值而進行適當的動作,這種耦合被稱爲控制耦合。
(5) 標記耦合 。若一個模塊A通過接口向兩個模塊B和C傳遞一個公共參數,那麼稱模塊B和C之間存在一個標記耦合。
(6) 數據耦合。模塊之間通過參數來傳遞數據,那麼被稱爲數據耦合。數據耦合是最低的一種耦合形式,系統中一般都存在這種類型的耦合,因爲爲了完成一些有意義的功能,往往需要將某些模塊的輸出數據作爲另一些模塊的輸入數據。
(7) 非直接耦合 。兩個模塊之間沒有直接關係,它們之間的聯繫完全是通過主模塊的控制和調用來實現的。
總結:耦合是影響軟件複雜程度和設計質量的一個重要因素,在設計上我們應採用以下原則:如果模塊間必須存在耦合,就儘量使用數據耦合,少用控制耦合,限制公共耦合的範圍,儘量避免使用內容耦合。
耦合強度,依賴於以下幾個因素:
(1)一個模塊對另一個模塊的調用;
(2)一個模塊向另一個模塊傳遞的數據量;
(3)一個模塊施加到另一個模塊的控制的多少;
(4)模塊之間接口的複雜程度。
NativeXml
1、文件名函數
文件名函數可以對文件的名稱、所在子目錄、驅動器和擴展名等進行操作。下表列出這些函數及其功能。
函數 說明
ExpandFileName() 返回文件的全路徑(含驅動器、路徑)
ExtractFileExt() 從文件名中抽取擴展名
ExtractFileName() 從文件名中抽取不含路徑的文件名
ExtractFilePath() 從文件名中抽取路徑名
ExtractFileDir() 從文件名中抽取目錄名
ExtractFileDrive() 從文件名中抽取驅動器名
ChangeFileExt() 改變文件的擴展名
ExpandUNCFileName() 返回含有網絡驅動器的文件全路徑
ExtractRelativePath() 從文件名中抽取相對路徑信息
ExtractShortPathName() 把文件名轉化爲DOS的8·3格式
MatchesMask() 檢查文件是否與指定的文件名格式匹配
ExtractFilePath(FileName:String)
該函數返回路徑名,其結尾字符總是“/”
ExtractFileDir(FileName:String)
該函數同樣返回路徑名,但不包括結尾的字符“/”,除非返回的路徑是根目錄。
下面就把這些函數作一一介紹:
⑴ExpandFileName()
原型:extern PACKAGE AnsiString __fastcall ExpandFileName(const AnsiString FileName);
功能:返回文件的全路徑(含驅動器、路徑)
參數:FileName:要處理的文件名
例:ShowMessage(ExpandFileName(Application->ExeName));//顯示你的程序文件名,如C:/MyBCB/Sample1.EXE
⑵ExtractFileExt()
原型:extern PACKAGE AnsiString __fastcall ExtractFileExt(const AnsiString FileName);
功能:從文件名中抽取擴展名
參數:FileName:要處理的文件名(全路徑)
例:ShowMessage(ExtractFileExt(Application->ExeName));//顯示".exe"
⑶ExtractFileName()
原型:extern PACKAGE AnsiString __fastcall ExtractFileName(const AnsiString FileName);
功能:從文件名中抽取不含路徑的文件名
參數:FileName:要處理的文件名
例:ShowMessage(ExtractFileExt("c://Winnt//SOL.EXE"));//顯示"SOL.EXE"
⑷ExtractFilePath()
原型:extern PACKAGE AnsiString __fastcall ExtractFilePath(const AnsiString FileName);
功能:從文件名中抽取路徑名
參數:FileName:要處理的文件名
例:ShowMessage(ExtractFilePath("Winnt//SOL.EXE"));//顯示"Winnt/"
⑸ExtractFileDir()
原型:extern PACKAGE AnsiString __fastcall ExtractFileDir(const AnsiString FileName);
功能:從文件名中抽取目錄名(和上個函數不同,不包括最後的"/")
參數:FileName:要處理的文件名
例:ShowMessage(ExtractFileDir("Winnt//SOL.EXE"));//顯示"Winnt",注意和上個函數的區別
⑹ExtractFileDrive()
原型:extern PACKAGE AnsiString __fastcall ExtractFileDrive(const AnsiString FileName);
功能:從文件名中抽取驅動器名
參數:FileName:要處理的文件名
例:ShowMessage(ExtractFileDrive("c://Winnt//SOL.EXE"));//顯示"c:"
⑺ChangeFileExt()
原型:extern PACKAGE System::AnsiString __fastcall ChangeFileExt(const System::AnsiString FileName, const System::AnsiString Extension);
功能:更改文件名的擴展名,不是對真正的文件進行改名,只是對文件名這個字符串進行處理
參數:FileName:要改名的文件名,Extension:新的擴展名
例:ShowMessage(ChangeFileExt("c://Winnt//SOL.EXE",".OOO"));//顯示"c:/winnt/SOL.OOO"
⑻ExpandUNCFileName()
原型:extern PACKAGE AnsiString __fastcall ExpandUNCFileName(const AnsiString FileName);
功能:返回含有網絡驅動器的文件全路徑,格式爲://機器名/共享名/文件名
參數:FileName:要處理的文件名
例:ShowMessage(ExpandUNCFileName("F://Winnt//SOL.EXE"));/*如果F:是映射的網絡驅動器,則顯示"
⑼ExtractRelativePath()
原型:extern PACKAGE AnsiString __fastcall ExtractRelativePath(const AnsiString BaseName, const AnsiString DestName);
功能:從文件名中抽取相對路徑信息,如"../sss/ss.asd"這種形式
參數:BaseName:基準文件名;DestName:目標文件名
例:ShowMessage(ExtractRelativePath("D://Source//c//1.123","D://Source//Asm//dz.asm"));/*顯示"../asm/dz.asm"*/
⑽ExtractShortPathName()
原型:extern PACKAGE AnsiString __fastcall ExtractShortPathName(const AnsiString FileName);
功能:把文件名轉換爲DOS的8、3格式
參數:FileName:要處理的文件名
例:ShowMessage(ExtractShortPathName("E://Program Files//Dual Wheel Mouse//4dmain.exe"));/*顯示"E:/Progra~1/dualwh~1/4dmain.exe"*/
⑾MatchesMask()
原型:extern PACKAGE bool __fastcall MatchesMask(const AnsiString Filename, const AnsiString Mask);
功能:檢查文件是否與指定的文件名格式匹配
參數:FileName:要處理的文件名;Mask:文件名格式,支持通配符
例:ShowMessage(MatchesMask("Lxf.exe","*.?x?));//顯示"true"
順序函數:
順序函數 |
引用形式 |
函數功能描述 |
序數函數 |
Ord(x); |
返回數據x的序數 |
前趨函數 |
Pred(x); |
返回數據x的前趨值。如果將Pred函數用於第一個數據,就可能產生一個編譯時的錯誤 |
後繼函數 |
Succ(x); |
返回數據x的後繼值。如果將Succ函數用於最後一個數據,就可能產生一個編譯時的錯誤 |
首序數函數 |
Low(x); |
返回順序型數據x取值集合中的第一個值(序數最小)。它還可以返回數組的第一個元素 |
末序數函數 |
High(x); |
返回順序型數據x取值集合中的最末一個值(序數最大),它還可以返回數組的最末一個元素 |
Delphi提供內部對話框有兩種。
第一種:信息輸出對話框Showmessage過程、ShowMessageFmt過程、MessageDlg函數、MessageDlgPos函數、CreateMessageDialog函數。
第二種:信息輸入對話框InputBox函數、InputQuery函數。
Delphi2010 String、ANSIString及TBytes之間的轉換
一、string轉爲ansistring
1、直接賦值 (有警告)
2、ansistring()類型強制轉換。(無警告)
二、ansistring 轉爲string
1、直接賦值 (有警告)
2、string()類型強制轉換。(無警告)
三、string 轉爲Tbytes
1、bytes:= bytesof(str) 已轉爲ansi編碼
2、bytes:= widebytesof(str) UNICODE 編碼
四、ansistring 轉爲Tbytes
1、bytes:= bytesof(str) ansi編碼
2、bytes:= widebytesof(string(str)) UNICODE 編碼
五、Tbytes 轉爲string
1、 str:=stringof(bytes) Tbytes 爲ansi編碼
2、 str:=widestringof(bytes) Tbytes 爲unicode編碼
六、PChar轉String
用StrPas函數,StrPas(PChar):AnsiString;
解決中文亂碼問題:
TEncoding.UTF8.GetBytes
TEncoding.UTF8.GetString
多線程學習:
function CreateThread(
lpThreadAttributes: Pointer; {安全設置}
dwStackSize: DWORD; {堆棧大小}
lpStartAddress: TFNThreadStartRoutine; {入口函數}
lpParameter: Pointer; {函數參數}
dwCreationFlags: DWORD; {啓動選項}
var lpThreadId: DWORD {輸出線程 ID }
): THandle; stdcall; {返回線程句柄}
當前程序是一個進程, 進程只是一個工作環境, 線程是工作者;
每個進程都會有一個啓動線程(或叫主線程), 也就是說: 我們之前大量的編碼都是寫給這個主線程的;
ExitThread(0); 就是退出這個主線程;
系統不允許一個沒有線程的進程存在, 所以程序就退出了.
另外: ExitThread 函數的參數是一個退出碼, 這個退出碼是給之後的其他函數用的, 這裏隨便給個無符號整數即可.
或許你會說: 這個 ExitThread 挺好用的; 其實不管是用 API 還是用 TThread 類寫多線程, 我們很少用到它; 因爲:
1、假如直接使用 API 的 CreateThread, 它執行完入口函數後會自動退出, 無需 ExitThread;
2、用 TThread 類建立的線程又絕不能使用 ExitThread 退出; 因爲使用 TThread 建立線程時會同時分配更多資源(譬如你自定義的成員、還有它的祖先類(TObject)分配的資源等等), 如果用 ExitThread 給草草退出了, 這些資源將得不到釋放而導致內存泄露. 儘管 Delphi 提供了 EndThread(其內部調用 ExitThread), 這也不需要我們手動操作(假如非要手動操作也是件很麻煩的事情, 因爲很多時候你不知道線程是什麼時候執行完畢的).
除了 CreateThread, 還有一個 CreateRemoteThread, 可在其他進程中建立線程
CreateThread 的倒數第二個參數 dwCreationFlags(啓動選項) 有兩個可選值:
0: 線程建立後立即執行入口函數;
CREATE_SUSPENDED: 線程建立後會掛起等待.
可用 ResumeThread 函數是恢復線程的運行; 可用 SuspendThread 再次掛起線程.
這兩個函數的參數都是線程句柄, 返回值是執行前的掛起計數.
什麼是掛起計數?
SuspendThread 會給這個數 +1; ResumeThread 會給這個數 -1; 但這個數最小是 0.
當這個數 = 0 時, 線程會運行; > 0 時會掛起.
如果被 SuspendThread 多次, 同樣需要 ResumeThread 多次才能恢復線程的運行