国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > PHP > 正文

數據源架構模式 表入口 行入口 活動記錄 數據映射器

2024-05-04 21:50:35
字體:
來源:轉載
供稿:網友

數據源架構模式 - 表入口模式

表入口模式充當數據庫表訪問入口的對象,一個實例處理表中的所有行。

可以理解為對之前分散在各個頁面的sql語句進行封裝,一張表就是一個對象,該對象處理所有與該表有關的業務邏輯,很好的提高了代碼的復用性。

現在想起來,當初剛畢業那會兒,經常使用表入口模式。

具體的實現方式參見代碼:

database.php

  1. <?php    
  2. class Database{   
  3.     //只是為了演示,通常情況下數據庫的配置是會單獨寫在配置文件中的   
  4.     private static $_dbConfig = array(   
  5.         'host' => '127.0.0.1',   
  6.         'username' => 'root',   
  7.         'pwd' => '',   
  8.         'dbname' => 'bussiness'   
  9.         );   
  10.     
  11.     private static $_instance;   
  12.     
  13.     public static function getInstance(){   
  14.         if(is_null(self::$_instance)){   
  15.             self::$_instance = new mysqli(self::$_dbConfig['host'], self::$_dbConfig['username'], self::$_dbConfig['pwd'], self::$_dbConfig['dbname']);    
  16.             if(self::$_instance->connect_errno){   
  17.                 throw new Exception(self::$_instance->connect_error);   
  18.             }   
  19.         }   
  20.         return self::$_instance;   
  21.     }   
  22.     
  23.     

person.php

  1. <?php    
  2. require_once 'database.php';   
  3. class Person extends Database{   
  4.     
  5.     public $instance;   
  6.     
  7.     public $table = 'person';   
  8.     
  9.     public function __construct(){   
  10.         $this->instance = Person::getInstance();   
  11.     }   
  12.     
  13.     public function getPersonById($personId){   
  14.         $sql = "<a href="/"/tags.php/select//"" target="/"_blank/"">select</a> * from $this->table where id=$personId";   
  15.         echo $sql;   
  16.         return $this->instance->query($sql);   
  17.     }   
  18.     
  19.     /**其他的一些增刪改查操作方法...**/   

index.php

  1. require_once 'person.php';   
  2.     
  3. $person = new Person();   
  4. var_dump($person->getPersonById(1)->fetch_assoc());   
  5. die(); 

運行結果:

  1. select * from person where id=1   
  2. array (size=2)   
  3.   'id' => string '1' (length=1)   
  4.   'name' => string 'ben' (length=3)   

數據源架構模式 - 行入口模式

一、概念

行數據入口(Row Data Gateway):充當數據源中單條記錄入口的對象,每行一個實例。

二、簡單實現行數據入口

為了方便理解,還是先簡單實現:

  1. <?php 
  2.    
  3. /** 
  4.  * 企業應用架構 數據源架構模式之行數據入口 2010-09-27 sz 
  5.  * @author phppan.p#gmail.com  http://www.phppan.com 
  6.  * 哥學社成員(http://www.blog-brother.com/) 
  7.  * @package architecture 
  8.  */ 
  9. class PersonGateway { 
  10.    
  11.     private $_name
  12.     private $_id
  13.     private $_birthday
  14.    
  15.     public function __construct($id$name$birthday) { 
  16.         $this->setId($id); 
  17.         $this->setName($name); 
  18.         $this->setBirthday($birthday); 
  19.     } 
  20.    
  21.     public function getName() { 
  22.         return $this->_name; 
  23.     } 
  24.    
  25.     public function setName($name) { 
  26.         $this->_name = $name
  27.     } 
  28.    
  29.     public function getId() { 
  30.         return $this->_id; 
  31.     } 
  32.    
  33.     public function setId($id) { 
  34.         $this->_id = $id
  35.     } 
  36.    
  37.     public function getBirthday() { 
  38.         return $this->_birthday; 
  39.     } 
  40.    
  41.     public function setBirthday($birthday) { 
  42.         $this->_birthday = $birthday
  43.     } 
  44.    
  45.     /** 
  46.      * 入口類自身擁有更新操作 
  47.      */ 
  48.     public function update() { 
  49.         $data = array('id' => $this->_id, 'name' => $this->_name, 'birthday' => $this->_birthday); 
  50.    
  51.         $sql = "UPDATE person SET "
  52.         <a href="/"/tags.php/foreach//"" target="/"_blank/"">foreach</a> ($data as $field => $value) { 
  53.             $sql .= "`" . $field . "` = '" . $value . "',"
  54.         } 
  55.         $sql = <a href="/"/tags.php/substr//"" target="/"_blank/"">substr</a>($sql, 0, -1); 
  56.    
  57.         $sql .= " WHERE id = " . $this->_id; 
  58.    
  59.         return DB::query($sql); 
  60.     } 
  61.    
  62.     /** 
  63.      * 入口類自身擁有插入操作 
  64.      */ 
  65.     public function insert() { 
  66.         $data = array('name' => $this->_name, 'birthday' => $this->_birthday); 
  67.    
  68.         $sql = "INSERT INTO person "
  69.         $sql .= "(`" . implode("`,`"array_keys($data)) . "`)"
  70.         $sql .= " VALUES('" . implode("','"array_values($data)) . "')"
  71.    
  72.         return DB::query($sql); 
  73.     } 
  74.    
  75.     public static function load($rs) { 
  76.         /* 此處可加上緩存 */ 
  77.         return new PersonGateway($rs['id'] ? $rs['id'] : NULL, $rs['name'], $rs['birthday']); 
  78.     } 
  79.    
  80.    
  81. /** 
  82.  * 人員查找類 
  83.  */ 
  84. class PersonFinder { 
  85.    
  86.     public function find($id) { 
  87.         $sql = "SELECT * FROM person WHERE id = " . $id
  88.         $rs = DB::query($sql); 
  89.    
  90.         return PersonGateway::load($rs); 
  91.     } 
  92.    
  93.     public function findAll() { 
  94.         $sql = "SELECT * FROM person"
  95.         $rs = DB::query($sql); 
  96.    
  97.         $result = array(); 
  98.         if (is_array($rs)) { 
  99.             foreach ($rs as $row) { 
  100.                 $result[] = PersonGateway::load($row); 
  101.             } 
  102.         } 
  103.    
  104.         return $result
  105.     } 
  106.    
  107.    
  108. class DB { 
  109.    
  110.     /** 
  111.      * 這只是一個執行SQL的演示方法 
  112.      * @param string $sql   需要執行的SQL 
  113.      */ 
  114.     public static function query($sql) { 
  115.         echo "執行SQL: "$sql" <br />"
  116.    
  117.         if (strpos($sql'SELECT') !== FALSE) { //  示例,對于select查詢返回查詢結果 
  118.             return array('id' => 1, 'name' => 'Martin''birthday' => '2010-09-15'); 
  119.         } 
  120.     } 
  121.    
  122.    
  123. /** 
  124.  * 客戶端調用 
  125.  */ 
  126. class Client { 
  127.    
  128.     /** 
  129.      * Main program. 
  130.      */ 
  131.     public static function main() { 
  132.    
  133.    
  134.         header("Content-type:text/html; charset=utf-8"); 
  135.    
  136.         /* 寫入示例 */ 
  137.         $data = array('name' => 'Martin''birthday' => '2010-09-15'); 
  138.         $person = PersonGateway::load($data); 
  139.         $person->insert(); 
  140.    
  141.         /* 更新示例 */ 
  142.         $data = array('id' => 1, 'name' => 'Martin''birthday' => '2010-09-15'); 
  143.         $person = PersonGateway::load($data); 
  144.         $person->setName('Phppan'); 
  145.         $person->update(); 
  146.    
  147.         /* 查詢示例 */ 
  148.         $finder = new PersonFinder(); 
  149.         $person = $finder->find(1); 
  150.         echo $person->getName(); 
  151.   //Vevb.com 
  152.     } 
  153.    
  154.    
  155. Client::main(); 
  156. ?> 

三、運行機制

●行數據入口是單條記錄極其相似的對象,在該對象中數據庫中的每一列為一個域。

●行數據入口一般能實現從數據源類型到內存中類型的任意轉換。

●行數據入口不存在任何領域邏輯,如果存在,則是活動記錄。

●在實例可看到,為了從數據庫中讀取信息,設置獨立的OrderFinder類。當然這里也可以選擇不新建類,采用靜態查找方法,但是它不支持需要為不同數據源提供不同查找方法的多態。因此這里最好單獨設置查找方法的對象。

●行數據入口除了可以用于表外還可以用于視圖。需要注意的是視圖的更新操作。

●在代碼中可見“定義元數據映射”,這是一種很好的作法,這樣一來,所有的數據庫訪問代碼都可以在自動建立過程中自動生成。

四、使用場景

4.1 事務腳本

可以很好地分離數據庫訪問代碼,并且也很容易被不同的事務腳本重用。不過可能會發現業務邏輯在多處腳本中重復出現,這些邏輯可能在行數據入口中有用。不斷移動這些邏輯會使行數據入口演變為活動記錄,這樣減少了業務邏輯的重復。

4.2 領域模型

如果要改變數據庫的結構但不想改變領域邏輯,采用行數據入口是不錯的選擇。大多數情況,數據映射器更加適合領域模型。

行數據入口能和數據映射器一起配合使用,盡管這樣看起來有點多此一舉,不過,當行數據入口從元數據自動生成,而數據映射器由手動實現時,這種方法會很有效。

數據源架構模式 - 活動記錄

【活動記錄的意圖】

一個對象,它包裝數據表或視圖中某一行,封裝數據庫訪問,并在這些數據上增加了領域邏輯。

【活動記錄的適用場景】

適用于不太復雜的領域邏輯,如CRUD操作等。

【活動記錄的運行機制】

對象既有數據又有行為。其使用最直接的方法,將數據訪問邏輯置于領域對象中。

活動記錄的本質是一個領域模型,這個領域模型中的類和基數據庫中的記錄結構應該完全匹配,類的每個域對應表的每一列。

一般來說,活動記錄包括如下一些方法:

1、由數據行構造一個活動記錄實例;

2、為將來對表的插入構造一個新的實例;

3、用靜態查找方法來包裝常用的SQL查詢和返回活動記錄;

4、更新數據庫并將活動記錄中的數據插入數據庫;

5、獲取或設置域;

6、實現部分業務邏輯。

【活動記錄的優點和缺點】

優點:

1、簡單,容易創建并且容易理解。

2、在使用事務腳本時,減少代碼復制。

3、可以在改變數據庫結構時不改變領域邏輯。

4、基于單個活動記錄的派生和測試驗證會很有效。

缺點:

1、沒有隱藏關系數據庫的存在。

2、僅當活動記錄對象和數據庫中表直接對應時,活動記錄才會有效。

3、要求對象的設計和數據庫的設計緊耦合,這使得項目中的進一步重構很困難

【活動記錄與其它模式】

數據源架構模式之行數據入口:活動記錄與行數據入口十分類似。二者的主要差別是行數據入口 僅有數據庫訪問而活動記錄既有數據源邏輯又有領域邏輯。

【活動記錄的PHP示例】

  1. <?php   
  2. /**   
  3. * 企業應用架構 數據源架構模式之活動記錄 2010-10-17 sz   
  4. * @author phppan.p#gmail.com  http://www.phppan.com   
  5. * 哥學社成員(http://www.blog-brother.com/)   
  6. * @package architecture   
  7. */  
  8. /**   
  9. * 定單類   
  10. */  
  11. class Order {   
  12. /**   
  13. *  定單ID   
  14. * @var <type>   
  15. */  
  16. private $_order_id;   
  17. /**   
  18. * 客戶ID   
  19. * @var <type>   
  20. */  
  21. private $_customer_id;   
  22. /**   
  23. * 定單金額   
  24. * @var <type>   
  25. */  
  26. private $_amount;   
  27. public function __construct($order_id$customer_id$amount) {   
  28. $this->_order_id = $order_id;   
  29. $this->_customer_id = $customer_id;   
  30. $this->_amount = $amount;   
  31. }   
  32. /**   
  33. * 實例的刪除操作   
  34. */  
  35. public function delete() {   
  36. $sql = "DELETE FROM Order SET WHERE order_id = " . $this->_order_id . " AND customer_id = "  . $this->_customer_id;   
  37. return DB::query($sql);   
  38. }   
  39. /**   
  40. * 實例的更新操作   
  41. */  
  42. public function update() {   
  43. }   
  44. /**   
  45. * 插入操作   
  46. */  
  47. public function insert() {   
  48. }   
  49. public static function load($rs) {   
  50. return new Order($rs['order_id'] ? $rs['order_id'] : NULL, $rs['customer_id'], $rs['amount'] ? $rs['amount'] : 0);   
  51. }   
  52. }   
  53. class Customer {   
  54. private $_name;   
  55. private $_customer_id;   
  56. public function __construct($customer_id$name) {   
  57. $this->_customer_id = $customer_id;   
  58. $this->_name = $name;   
  59. }   
  60. /**   
  61. * 用戶刪除定單操作 此實例方法包含了業務邏輯   
  62. * 通過調用定單實例實現   
  63. * 假設此處是對應的刪除操作(實際中可能是一種以某字段來標記的假刪除操作)   
  64. */  
  65. public function deleteOrder($order_id) {   
  66. $order = Order::load(array('order_id' => $order_id'customer_id' => $this->_customer_id));   
  67. return $order->delete();   
  68. }   
  69. /**   
  70. * 實例的更新操作   
  71. */  
  72. public function update() {   
  73. }   
  74. /**   
  75. * 入口類自身擁有插入操作   
  76. */  
  77. public function insert() {   
  78. }   
  79. public static function load($rs) {   
  80. /* 此處可加上緩存 */  
  81. return new Customer($rs['customer_id'] ? $rs['customer_id'] : NULL, $rs['name']);   
  82. }   
  83. /**   
  84. * 根據客戶ID 查找   
  85. * @param integer $id   客戶ID   
  86. * @return  Customer 客戶對象   
  87. */  
  88. public static function find($id) {   
  89. return CustomerFinder::find($id);   
  90. }   
  91. }   
  92. /**   
  93. * 人員查找類   
  94. */  
  95. class CustomerFinder {   
  96. public static function find($id) {   
  97. $sql = "SELECT * FROM person WHERE customer_id = " . $id;   
  98. $rs = DB::query($sql);   
  99. return Customer::load($rs);   
  100. }   
  101. }   
  102. class DB {   
  103. /**   
  104. * 這只是一個執行SQL的演示方法   
  105. * @param string $sql   需要執行的SQL   
  106. */  
  107. public static function query($sql) {   
  108. echo "執行SQL: "$sql" <br />";   
  109. if (strpos($sql'SELECT') !== FALSE) { //  示例,對于select查詢返回查詢結果   
  110. return array('customer_id' => 1, 'name' => 'Martin');   
  111. }   
  112. }   
  113. }   
  114. /**   
  115. * 客戶端調用   
  116. */  
  117. class Client {   
  118. /**   
  119. * Main program.   
  120. */  
  121. public static function main() {   
  122. header("Content-type:text/html; charset=utf-8");   
  123. /* 加載客戶ID為1的客戶信息 */  
  124. $customer = Customer::find(1);   
  125. /* 假設用戶擁有的定單id為 9527*/  
  126. $customer->deleteOrder(9527);   
  127. }  //Vevb.com 
  128. }   
  129. Client::main();   
  130. ?> 

同前面的文章一樣,這僅僅是一個活動記錄的示例,關于活動記錄模式的應用,可以查看Yii框架中的DB類,在其源碼中有一個CActiveRecord抽象類,從這里可以看到活動記錄模式的應用

另外,如果從事務腳本中創建活動記錄,一般是首先將表包裝為入口,接著開始行為遷移,使表深化成為活動記錄。

對于活動記錄中的域的訪問和設置可以如yii框架一樣,使用魔術方法__set方法和__get方法。

數據源架構模式 - 數據映射器

一:數據映射器

關系型數據庫用來存儲數據和關系,對象則可以處理業務邏輯,所以,要把數據本身和業務邏輯糅雜到一個對象中,我們要么使用 活動記錄,要么把兩者分開,通過數據映射器把兩者關聯起來。

數據映射器是分離內存對象和數據庫的中間軟件層,下面這個時序圖描述了這個中間軟件層的概念:

數據源架構模式 表入口 行入口 活動記錄 數據映射器

在這個時序圖中,我們還看到一個概念,映射器需能夠獲取領域對象(在這個例子中,a Person 就是一個領域對象)。而對于數據的變化(或者說領域對象的變化),映射器還必須要知道這些變化,在這個時候,我們就需要 工作單元 模式(后議)。

從上圖中,我們仿佛看到 數據映射器 還蠻簡單的,復雜的部分是:我們需要處理聯表查詢,領域對象的繼承等。領域對象的字段則可能來自于數據庫中的多個表,這種時候,我們就必須要讓數據映射器做更多的事情。是的,以上我們說到了,數據映射器要能做到兩個復雜的部分:

1:感知變化;

2:通過聯表查詢的結果,為領域對象賦值;

為了感知變化以及與數據庫對象保持一致,則需要 標識映射(架構模式對象與關系結構模式之:標識域(Identity Field)),這通常需要有 標識映射的注冊表,或者為每個查找方法持有一個 標識映射,下面的代碼是后者:

  1. void Main() 
  2.     SqlHelper.ConnectionString = "Data Source=xxx;Initial Catalog=xxx;Integrated Security=False;User ID=sa;Password=xxx;Connect Timeout=15;Encrypt=False;TrustServerCertificate=False"
  3.     var user1 = User.FindUser("6f7ff44435f3412cada61898bcf0df6c"); 
  4.     var user2 = User.FindUser("6f7ff44435f3412cada61898bcf0df6c"); 
  5.     (user1 == user2).Dump(); 
  6.     "END".Dump(); 
  7.  
  8.     public abstract class BaseMode 
  9.     { 
  10.         public string Id {get; set;} 
  11.  
  12.         public string Name {get; set;} 
  13.     } 
  14.  
  15.     public class User : BaseMode 
  16.     { 
  17.         static UserMap map = new UserMap(); 
  18.         public static User FindUser(string id) 
  19.         { 
  20.             var user = map.Find(id); 
  21.             return user; 
  22.         } 
  23.     } 
  24.  
  25.     public class UserMap : AbstractMapper<User> 
  26.     { 
  27.         public User Find(string id) 
  28.         { 
  29.             return (User)AbstractFind(id); 
  30.         } 
  31.         
  32.         protected override User AbstractFind(string id) 
  33.         { 
  34.             var user = base.AbstractFind(id); 
  35.             if( user == null ) 
  36.             { 
  37.                 "is Null".Dump(); 
  38.                 string sql = "SELECT * FROM [EL_Organization].[User] WHERE ID=@Id"
  39.                 var pms = new SqlParameter[] 
  40.                 { 
  41.                     new SqlParameter("@Id", id) 
  42.                 }; 
  43.                 
  44.                 var ds = SqlHelper.ExecuteDataset(CommandType.Text, sql, pms); 
  45.                 user = DataTableHelper.ToList<User>(ds.Tables[0]).FirstOrDefault(); 
  46.                 if(user == null) 
  47.                 { 
  48.                     return null; 
  49.                 } 
  50.                 
  51.                 user = Load(user); 
  52.                 return user; 
  53.             } 
  54.             
  55.             return user; 
  56.         } 
  57.         
  58.         public List<User> FindList(string name) 
  59.         { 
  60.             // SELECT * FROM USER WHERE NAME LIKE NAME 
  61.             List<User> users = null; 
  62.             return LoadAll(users); 
  63.         } 
  64.         
  65.         public void Update(User user) 
  66.         { 
  67.             // UPDATE USER SET .... 
  68.         } 
  69.     } 
  70.     
  71.     public abstract class AbstractMapper<T> where T : BaseMode 
  72.     { 
  73.         // 這里的問題是,隨著對象消失,loadedMap就被回收 
  74.         protected Dictionary<string, T> loadedMap = new Dictionary<string, T>(); 
  75.         
  76.         protected T Load(T t) 
  77.         { 
  78.             if(loadedMap.ContainsKey(t.Id) ) 
  79.             { 
  80.                 return loadedMap[t.Id]; 
  81.             } 
  82.             else 
  83.             { 
  84.                 loadedMap.Add(t.Id, t); 
  85.                 return t; 
  86.             } 
  87.         } 
  88.         
  89.         protected List<T> LoadAll(List<T> ts) 
  90.         { 
  91.             for(int i=0; i < ts.Count; i++) 
  92.             { 
  93.                 ts[i] = Load(ts[i]); 
  94.             } 
  95.             
  96.             return ts; 
  97.         } 
  98.         
  99.         protected virtual T AbstractFind(string id) 
  100.         { 
  101.             if(loadedMap.ContainsKey(id)) 
  102.             { 
  103.                 return loadedMap[id]; 
  104.             } //Vevb.com 
  105.             else 
  106.             { 
  107.                 return null; 
  108.             } 
  109.         } 
  110.     } 

上面是一個簡單的映射器,它具備了 標識映射 功能。由于有標識映射,所以我們運行這段代碼得到的結果是:

數據源架構模式 表入口 行入口 活動記錄 數據映射器

回歸本問實質,問題:什么叫 “數據映射”

其實,這個問題很關鍵,UserMap 通過 Find 方法,將數據庫記錄變成了一個 User 對象,這就叫 “數據映射”,但是,真正起到核心作用的是 user = DataTableHelper.ToList<User>(ds.Tables[0]).FirstOrDefault();  這行代碼。更進一步的,DataTableHelper.ToList<T> 這個方法完成了 數據映射 功能。

那么,DataTableHelper.ToList<T> 方法具體干了什么事情,實際上,無非就是根據屬性名去獲取 DataTable 的字段值。這是一種簡便的方法,或者說,在很多業務不復雜的場景下,這也許是個好辦法,但是,因為業務往往是復雜的,所以實際情況下,我們使用這個方法的情況并不是很多,大多數情況下,我們需要像這樣編碼來完成映射:

someone.Name = Convert.ToString(row["Name"])

不要懷疑,上面這行代碼,就叫數據映射,任何高大上的概念,實際上就是那條你寫了很多遍的代碼。

1.1 EntityFramework 中的數據映射

這是一個典型的 EF 的數據映射類,

  1. public class CourseMap : EntityTypeConfiguration<Course> 
  2.     public CourseMap() 
  3.     { 
  4.         // Primary Key 
  5.         this.HasKey(t => t.CourseID); 
  6.  
  7.         // Properties 
  8.         this.Property(t => t.CourseID) 
  9.             .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 
  10.         this.Property(t => t.Title) 
  11.             .IsRequired() 
  12.             .HasMaxLength(100); 
  13.         // Table & Column Mappings 
  14.         this.ToTable("Course"); 
  15.         this.Property(t => t.CourseID).HasColumnName("CourseID"); 
  16.         this.Property(t => t.Title).HasColumnName("Title"); 
  17.         this.Property(t => t.Credits).HasColumnName("Credits"); 
  18.         this.Property(t => t.DepartmentID).HasColumnName("DepartmentID"); 
  19.  
  20.         // Relationships 
  21.         this.HasMany(t => t.People) 
  22.             .WithMany(t => t.Courses) 
  23.             .Map(m => 
  24.                 { 
  25.                     m.ToTable("CourseInstructor"); 
  26.                     m.MapLeftKey("CourseID"); 
  27.                     m.MapRightKey("PersonID"); 
  28.                 }); 
  29.         this.HasRequired(t => t.Department) 
  30.             .WithMany(t => t.Courses) 
  31.             .HasForeignKey(d => d.DepartmentID); 
  32.     } 

我們可以看到,EF 的數據映射,那算是真正的數據映射。最基本的,其在內部無非是干了一件這樣的事情:

數據庫是哪個字段,對應的內存對象的屬性是哪個屬性。

最終,它都是通過一個對象工廠把領域模型生成出來,其原理大致如下:

  1. internal static Course BuildCourse(IDataReader reader) 
  2.     Course course = new Course(reader[FieldNames.CourseId]); 
  3.     contract.Title = reader[FieldNames.Title].ToString(); 
  4.     … 
  5.     return contract; 

二:倉儲庫

UserMap 關于 數據映射器 的概念是不是覺得太重了?因為它干了 映射 和 持久化 的事情,它甚至還得持有 工作單元。那么,如果我們能不能像 EF 一樣,映射器 只干映射的事情,而把其余事情分出去呢?可以,分離出去的這部分就叫做 倉儲庫。

三:再多說一點 DataTableHelper.ToList<T>,簡化的數據映射器

其實就是 DataTable To List 了。如果你在用 EF 或者 NHibernate 這樣的框架,那么,就用它們提供的映射器好了(嚴格來說,你不是在使用它們的映射器。因為這些框架本身才是在使用自己的映射器,我們只是在配置映射器所要的數據和關系而已,有時候,這些配置是在配置文件中,有時候是在字段或屬性上加 Attribute,有時候則是簡單但龐大的單行代碼)。我們當然也可以創建自己的 標準的 映射器,Tim McCarthy 在 《領域驅動設計 C# 2008 實現》 中就實現了這樣的映射器。但是,EF 和 NHibernate  固然很好,但是很多時候我們還是不得不使用 手寫SQL,因為:

1:EF 和 NHibernate 是需要學習成本的,這代表者團隊培訓成本高,且易出錯的;

2:不應放棄 手寫SQL 的高效性。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 贡觉县| 浪卡子县| 炎陵县| 绥棱县| 万山特区| 怀仁县| 江北区| 萝北县| 咸丰县| 涡阳县| 巴东县| 盈江县| 柳河县| 农安县| 泉州市| 舟山市| 赣榆县| 苏州市| 太谷县| 桐柏县| 建瓯市| 彰化县| 田林县| 浮梁县| 保山市| 宣城市| 安乡县| 土默特左旗| 岑溪市| 汽车| 龙口市| 错那县| 敖汉旗| 鄂托克旗| 于都县| 临漳县| 青河县| 宁海县| 新宾| 喀喇沁旗| 灯塔市|