Data source schema Mode table entry row entry activity record Data mapper

Source: Internet
Author: User
Tags abstract foreach instance method yii


Data source schema mode-table entry mode

Table entry mode acts as an object in the database table access entry, and one instance handles all rows in the table.

can be understood to encapsulate SQL statements that were previously dispersed across pages, and a table is an object that handles all the business logic associated with the table, which improves the reusability of the code.

Now, when I first graduated, I used the table-entry mode a lot.

Specific implementation See Code:


<?php    class database{       //Just for demonstration, Typically, the configuration of a database is written separately in the configuration file        private static $_dbConfig =  Array (            ' host '  =>  ' ',             ' username '  =>  ' root ',             ' pwd '  =>  ',             ' dbname '  =>  ' bussiness '             );          private static $_instance;           public static function getinstance () {            if (Is_null (self::$_instance)) {              &nbsP; self::$_instance = new mysqli (self::$_dbconfig[' host '], self::$_dbconfig[') Username '], self::$_dbconfig[' pwd '], self::$_dbconfig[' dbname '];                 if (Self::$_instance->connect_errno) {                    throw  new exception (self::$_instance->connect_error);         
      }           }           return self::$_instance;        }        }


<?php    require_once  ' database.php ';   class person extends  database{          public  $instance;           public  $table  =  ' person ';           Public function __construct () {            $this-> Instance = person::getinstance ();       }           public function getpersonbyid ($personId) {             $sql  =  "select * from  $this->table where id=$ PersonId ";           echo  $sql;            return  $this->instance->query ($sql);        }          /** Some other additions and deletions to check the operation method ...**/  } 


require_once ' person.php ';  
$person = new Person ();  
Var_dump ($person->getpersonbyid (1)->FETCH_ASSOC ());
die ();

Run Result:

SELECT * FROM person where id=1
Array (size=2)
' id ' => string ' 1 ' (length=1)
' Name ' => string ' Ben ' (length=3)

Data source schema mode-row entry mode

First, the concept

Row Data Portal: an object that acts as a single record entry in a data source, one instance per row.

Second, the simple implementation of the row data entry

For the sake of understanding, it is easy to realize first:

&lt;?php &nbsp;/** &nbsp;*&nbsp; Enterprise Application architecture &nbsp; Data Source architecture mode row data entry &nbsp;2010-09-27&nbsp;sz &nbsp;*&nbsp; @author &nbsp; Member of;&nbsp; &nbsp;*&nbsp; Society ( &nbsp;* &nbsp; @package &nbsp;architecture &nbsp;*/class&nbsp;persongateway&nbsp;{&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;private
&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;__construct ($id,&nbsp; $name,&nbsp; $birthday) &nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;setid ($id);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;setname ($name);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;setbirthday ($birthday); &NBSP;&NBSP;&NBSP;&NBSP} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;getname () &nbsp;{&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp; $this-&gt;_name; &NBSP;&NBSP;&NBSP;&NBSP} &nbsp; &NBSP;&NBSP;&NBSP;&NBsp;public&nbsp;function&nbsp;setname ($name) &nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;_
name&nbsp;=&nbsp; $name; &NBSP;&NBSP;&NBSP;&NBSP} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;getid () &nbsp;{&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp; $this-&gt;_id; &NBSP;&NBSP;&NBSP;&NBSP} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;setid ($id) &nbsp;{&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;_id&nbsp;=&nbsp; $id; &NBSP;&NBSP;&NBSP;&NBSP} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;getbirthday () &nbsp;{&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp; $this-&gt;_birthday;
&NBSP;&NBSP;&NBSP;&NBSP} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;setbirthday ($birthday) &nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;_birthday&nbsp;=&nbsp; $birthday;
&NBSP;&NBSP;&NBSP;&NBSP} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp; entry class itself has update operations &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;update () &nbsp;{&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; $data &nbsp;=&nbsp;array (' id ' &nbsp;=&gt;&nbsp; $this-&gt;_id,&nbsp; ' name ' &nbsp;=&gt;
&nbsp; $this-&gt;_name,&nbsp; ' birthday ' &nbsp;=&gt;&nbsp; $this-&gt;_birthday);
&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sql &nbsp;=&nbsp; "update&nbsp;person&nbsp;set&nbsp;"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp; ($data &nbsp;as&nbsp; $field &nbsp;=&gt;&nbsp; $value ) &nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sql &nbsp;.=&nbsp; "'" &NBSP;.
&nbsp; $field &nbsp;.&nbsp; "' &nbsp;=&nbsp; '" &nbsp;.&nbsp; $value &nbsp;.&nbsp; "',"; &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sql &nbsp;=
&nbsp;substr ($sql, &nbsp;0,&nbsp;-1); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sql &nbsp;.=&nbsp; "&nbsp;WHERE&nbsp;id&nbsp;=&nbsp;"
&nbsp;.&nbsp; $this-&gt;_id; &nbsp; &NBSP;&NBSP; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;db::query ($sql);
&NBSP;&NBSP;&NBSP;&NBSP} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp; entry class itself has insert operations &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;insert () &nbsp;{&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $data &nbsp;=&nbsp;array (' name ' &nbsp;=&gt;&nbsp; $this-&gt;_name,&nbsp; ')
Birthday ' &nbsp;=&gt;&nbsp; $this-&gt;_birthday);
&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sql &nbsp;=&nbsp; "insert&nbsp;into&nbsp;person&nbsp;"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sql &nbsp;.=&nbsp; "(' &nbsp;.&nbsp;implode ', '", &nbsp;array_
Keys ($data)) &nbsp;.&nbsp; "')"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sql &nbsp;.=&nbsp; "&nbsp;values ('" &nbsp;.&nbsp;implode) ("', '",
&nbsp;array_values ($data)) &nbsp;.&nbsp; "')";
&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;db::query ($sql); &NBSP;&NBSP;&NBSP;&NBSP} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;stAtic&nbsp;function&nbsp;load ($rs) &nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp; here can be added cache &nbsp;* /&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;persongateway ($rs [' id ']&nbsp;?&nbsp; $rs [
' ID ']&nbsp;:&nbsp;null,&nbsp; $rs [' name '],&nbsp; $rs [' birthday ']); &NBSP;&NBSP;&NBSP;&NBSP} &nbsp;} &nbsp;/** &nbsp;*&nbsp; staff lookup class &nbsp;*/class&nbsp;personfinder&nbsp;{&nbsp; &nbsp;& Nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;find ($id) &nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$
sql&nbsp;=&nbsp; "select&nbsp;*&nbsp;from&nbsp;person&nbsp;where&nbsp;id&nbsp;=&nbsp;" &nbsp;.&nbsp; $id;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $rs &nbsp;=&nbsp;db::query ($sql);
&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;persongateway::load ($RS); &NBSP;&NBSP;&NBSP;&NBSP} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;findall () &nbsp;{&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sql &nbsp;=&nbsp; "Select&nbsp;*&nbsp;from&nbsp;person"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $rs &nbsp;=&nbsp;db::query ($sql);
&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $result &nbsp;=&nbsp;array (); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp; (Is_array ($rs)) &nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp; ($rs &nbsp;as&nbsp; $row) &nbsp;{&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $result []&nbsp;=&nbsp;persongateway::
Load ($row); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp; $result; &NBSP;&NBSP;&NBSP;&NBSP} &nbsp;} &nbsp; class&nbsp;db&nbsp;{&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;& nbsp;&nbsp;*&nbsp; This is just a demo method for executing SQL &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp; @param &nbsp;string&nbsp; $sql &nbsp;&nbsp; &nbsp; SQL &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp to execute;p ublic&nbsp;static&nbsp;function&nbsp;query ($sql) &nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo
&nbsp; "Executive sql:&nbsp;",&nbsp; $sql,&nbsp; "&nbsp;&lt;br&nbsp;/&gt;"; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp; (Strpos ($sql,&nbsp; ' SELECT ') &nbsp;!==&nbsp;false &nbsp;{&nbsp;//&nbsp;&nbsp; example, returns query results for a select query &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;return&nbsp;array (' id ' &nbsp;=&gt;&nbsp;1,&nbsp; ' name ' &nbsp;=&gt;&nbsp; ' Martin ',&nbsp; ' birthday ')
&nbsp;=&gt;&nbsp; ' 2010-09-15 ');
&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP} &nbsp;&nbsp;&nbsp;&nbsp} &nbsp;} &nbsp;/** &nbsp;*&nbsp; client invocation &nbsp;*/class&nbsp;client&nbsp;{&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;main
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;function&nbsp;main () &nbsp;{ &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;header ("Content-type:text/html;&nbsp;charset=utf-8
"); &nBsp &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp; Write Sample &nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp; $data &nbsp;=&nbsp;array (' name ' &nbsp;=&gt;&nbsp; ' Martin ',&nbsp; ' birthday ' &nbsp;=&gt;&nbsp; ' 2010-09-15 ');
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $person &nbsp;=&nbsp;persongateway::load ($data);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $person-&gt;insert (); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp; Update Sample &nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; $data &nbsp;=&nbsp;array (' id ' &nbsp;=&gt;&nbsp;1,&nbsp; ' name ' &nbsp;=&gt;&nbsp; ' Martin ',&nbsp; ')
Birthday ' &nbsp;=&gt;&nbsp; ' 2010-09-15 ');
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $person &nbsp;=&nbsp;persongateway::load ($data);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $person-&gt;setname (' Phppan ');
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $person-&gt;update (); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp; Query Sample &nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $finder &nbsp;=&nbsp;new&nbsp;personfinder ();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $person &nbsp;=&nbsp; $finder-&gt;find (1);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp; $person-&gt;getname (); &nbsp; &NBSP;&NBSP;&NBSP;&NBSP} &nbsp;} &nbsp; Client::main ();?&gt;

iii. operating mechanism

A row data entry is an object that is extremely similar to a single record, in which each column in the database is a field.

A row data entry can generally implement arbitrary conversions from the data source type to the type in memory.

There is no domain logic for the row data entry, and if it exists, it is an active record.

As you can see in the instance, set up a separate Orderfinder class to read information from the database. Of course, you can also choose not to create a new class, the static lookup method, but it does not support the need for different data sources to provide different lookup methods of polymorphism. Therefore, it is best to set the object of the lookup method individually.

Row data portals can be used for views in addition to tables. What you need to be aware of is the update operation of the view.

It is a good practice to have "define metadata mappings" in your code, so that all database access code can be automatically generated during automatic setup.

Iv. use of the scene

4.1 Transaction Scripts

The database access code can be well separated and easily reused by different transaction scripts. However, you may find that the business logic repeats itself in multiple scripts that might be useful in a row data entry. Moving these logic over and over makes the row data entry evolve into an activity record, reducing the duplication of business logic.

4.2 Field Models

If you want to change the structure of the database but do not want to change the domain logic, the use of row data entry is a good choice. In most cases, the data mapper is more suited to the domain model.

Row data entry can be used in conjunction with the data mapper, although this may seem a bit superfluous, however, this method works well when the row data entry is automatically generated from the metadata and the data mapper is implemented manually.

Data source schema mode-activity record

"Intent of the activity record"

An object that wraps a row in a datasheet or view, encapsulates database access, and adds domain logic to the data.

"Applicable scenario for Active records"

Applies to less complex domain logic, such as CRUD operations.

"Operating mechanism for Activity records"

objects have both data and behavior. It uses the most direct method of putting data access logic into the domain object.

The nature of the activity record is a domain model in which the class in the domain model and the record structure in the base database should match exactly, each of the fields of the class corresponds to each column of the table.

In general, activity records include the following methods:

1, the data row constructs an activity record instance;

2. To construct a new example for the future insertion of the table;

3, using static search method to wrap the commonly used SQL query and return activity records;

4. Update the database and insert the data in the activity record into the database;

5, get or set the domain;

6, the implementation of part of the business logic.

"Advantages and disadvantages of activity records"


1, simple, easy to create and easy to understand.

2, in the use of transaction scripts, reduce code replication.

3, you can change the database structure without changing the domain logic.

4. Derivation and test validation based on a single activity record can be effective.


1, there is no hidden relational database exists.

2. The active record is valid only if the active Record object and the table in the database correspond directly.

3, the requirements of the object design and the design of the database tightly coupled, which makes the project further refactoring is difficult

"Activity record and other modes"

Data source schema-type row data entry: Activity records are very similar to row data portals. The main difference between the two is that the row data entry has only database access and activity records have both data source logic and domain logic.

"PHP Examples of active records"

&lt;?php&nbsp;&nbsp;/**&nbsp;&nbsp; *&nbsp; Enterprise Application architecture &nbsp; Data Source architecture mode activity Records &nbsp;2010-10-17&nbsp;sz&nbsp;&nbsp; *&nbsp;@ author&nbsp;;&nbsp;;&nbsp; *&nbsp;, member of the Society of Columbia (http:// &nbsp;&nbsp; *&nbsp; @package &nbsp;architecture&nbsp;&nbsp; */&nbsp;/**&nbsp;&nbsp; *&nbsp; Order &nbsp;&nbsp; */&nbsp; class&nbsp;order&nbsp;{&nbsp;&nbsp;/**&nbsp;&nbsp; *&nbsp;&nbsp; orders id&nbsp;&nbsp; var&nbsp;&lt;type&gt;&nbsp;&nbsp; */&nbsp; private&nbsp;$_order_id;&nbsp;&nbsp;/**&nbsp;&nbsp; *&nbsp; customer id&nbsp; &nbsp; *&nbsp; @var &nbsp;&lt;type&gt;&nbsp;&nbsp; */&nbsp; private&nbsp;$_customer_id;&nbsp;&nbsp;/**&nbsp;&nbsp; *
&nbsp; Order Amount &nbsp;&nbsp; *&nbsp; @var &nbsp;&lt;type&gt;&nbsp;&nbsp; */&nbsp; private&nbsp;$_amount;&nbsp;&nbsp; Public&nbsp;function&nbsp;__construct ($order _id,&nbsp; $customer _id,&nbsp; $amount) &nbsp;{&nbsp;&nbsp; $this-&gt; _order_id&nbsp;=&nbsp; $order _id;&nbsp;&nbsp; $this-&gt;_customer_id&nbsp;=&nbsp; $customer _id;&nbsp;&nbsp; $this- ";_amount&nbsp;=&nbsp; $amount;&nbsp;&nbsp;}&nbsp;&nbsp;/**&nbsp;&nbsp; *&nbsp; Instance Delete operations &nbsp;&nbsp; */&nbsp; public &nbsp;function&nbsp;delete () &nbsp;{&nbsp;&nbsp; $sql &nbsp;=&nbsp; "delete&nbsp;from&nbsp;order&nbsp;set&nbsp; where&nbsp;order_id&nbsp;=&nbsp; "&nbsp;.&nbsp; $this-&gt;_order_id&nbsp;.&nbsp;" &nbsp;and&nbsp;customer_id &nbsp;=&nbsp; &nbsp;&nbsp;.&nbsp; $this-&gt;_customer_id;&nbsp;&nbsp; return&nbsp;db::query ($sql);&nbsp;&nbsp;} &nbsp;&nbsp;/**&nbsp;&nbsp; *&nbsp; Instance update operations &nbsp;&nbsp; */&nbsp; public&nbsp;function&nbsp;update () &nbsp;{&nbsp; &nbsp;}&nbsp;&nbsp;/**&nbsp;&nbsp; *&nbsp; insert Operation &nbsp;&nbsp; */&nbsp; Public&nbsp;function&nbsp;insert () &nbsp;{ &nbsp;&nbsp;}&nbsp;&nbsp; public&nbsp;static&nbsp;function&nbsp;load ($rs) &nbsp;{&nbsp;&nbsp; return&nbsp;new &nbsp;order ($rs [' order_id ']&nbsp;?&nbsp; $rs [' order_id ']&nbsp;:&nbsp;null,&nbsp; $rs [' customer_id '],&nbsp; $rs [] Amount ']&nbsp;?&nbsp; $rs [' Amount ']&nbsp;:&nbsp;0);&nbsp;&nbsp;}&nbsp;&nbsp;}&nbsp;&nbsp; Class&nbsp;customer &nbsp;{&nbsp;&nbsp; private&nbsp;$_name;&nbsp;&nbsp; private&nbsp;$_customer_id;&nbsp;&nbsp; public&nbsp;function&nbsp;__ Construct ($customer _id,&nbsp; $name) &nbsp;{&nbsp;&nbsp; $this-&gt;_customer_id&nbsp;=&nbsp; $customer _id;&nbsp; &nbsp; $this-&gt;_name&nbsp;=&nbsp; $name;&nbsp;&nbsp;}&nbsp;&nbsp;/**&nbsp;&nbsp; *&nbsp; User Delete order operation &nbsp; This instance method includes business logic &nbsp;&nbsp; *&nbsp; by invoking the order instance to implement &nbsp;&nbsp; *&nbsp; assuming that this is the corresponding delete operation (in practice it might be a fake delete operation marked with a field) &nbsp;&nbsp; */ &nbsp; Public&nbsp;function&nbsp;deleteorder ($order _id) &nbsp;{&nbsp;&nbsp; $order &nbsp;=&nbsp;order::load (Array (
' order_id ' &nbsp;=&gt;&nbsp; $order _id,&nbsp; ' customer_id ' &nbsp;=&gt;&nbsp; $this-&gt;_customer_id);&nbsp;&nbsp;
return&nbsp; $order-&gt;delete ();&nbsp;&nbsp;}&nbsp;&nbsp;/**&nbsp;&nbsp; *&nbsp; Instance update operations &nbsp;&nbsp; */&nbsp; Public&nbsp;function&nbsp;update () &nbsp;{&nbsp;&nbsp;}&nbsp;&nbsp;/**&nbsp;&nbsp; *&nbsp; Portal class itself has insert operations &nbsp; &nbsp; */&nbsp; Public&nbsp;function&nbsp;insert () &nbsp;{&nbsp;&nbsp;}&nbsp;&nbsp; public&nbsp;static&nbsp; function&nbsp;Load ($rs) &nbsp;{&nbsp;&nbsp;/*&nbsp; Here you can add caching &nbsp;*/&nbsp; return&nbsp;new&nbsp;customer ($rs [' customer_id '] &nbsp;?&nbsp; $rs [' customer_id ']&nbsp;:&nbsp;null,&nbsp; $rs [' name ']);&nbsp;&nbsp;}&nbsp;&nbsp;/**&nbsp;&nbsp; * &nbsp; According to customer id&nbsp; find &nbsp;&nbsp; *&nbsp; @param &nbsp;integer&nbsp; $id &nbsp;&nbsp;&nbsp; customer id&nbsp;&nbsp; *&nbsp;@ return&nbsp;&nbsp;customer&nbsp; Customer Object &nbsp;&nbsp; */&nbsp; public&nbsp;static&nbsp;function&nbsp;find ($id) &nbsp;{ &nbsp;&nbsp; Return&nbsp;customerfinder::find ($id);&nbsp;&nbsp;}&nbsp;&nbsp;}&nbsp;&nbsp;/**&nbsp;&nbsp; *&nbsp; People lookup class &nbsp;&nbsp; */&nbsp; class&nbsp;customerfinder&nbsp;{&nbsp;&nbsp; public&nbsp;static&nbsp;function&nbsp; Find ($id) &nbsp;{&nbsp;&nbsp; $sql &nbsp;=&nbsp; "select&nbsp;*&nbsp;from&nbsp;person&nbsp;where&nbsp;customer_id &nbsp;=&nbsp; &nbsp;.&nbsp; $id;&nbsp;&nbsp; $rs &nbsp;=&nbsp;db::query ($sql);&nbsp;&nbsp; Return&nbsp;customer:: Load ($rs);&nbsp;&nbsp;}&nbsp;&nbsp;}&nbsp;&nbsp; class&nbsp;db&nbsp;{&nbsp;&nbsp;/**&nbsp;&nbsp; *&nbsp; This is just aExecute SQL Demo methods &nbsp;&nbsp; *&nbsp; @param &nbsp;string&nbsp; $sql &nbsp;&nbsp;&nbsp; need to perform sql&nbsp;&nbsp; */&nbsp; public &nbsp;static&nbsp;function&nbsp;query ($sql) &nbsp;{&nbsp;&nbsp; echo&nbsp; "executive sql:&nbsp;",&nbsp; $sql,&nbsp; " &nbsp;&lt;br&nbsp;/&gt; ";&nbsp;&nbsp; if&nbsp; (Strpos ($sql,&nbsp; ' SELECT ') &nbsp;!==&nbsp;false) &nbsp;{&nbsp;// &nbsp;&nbsp; example, return query results for select query &nbsp;&nbsp; return&nbsp;array (' customer_id ' &nbsp;=&gt;&nbsp;1,&nbsp; ' name ') &nbsp;=&gt;&nbsp; ' Martin ';&nbsp;&nbsp;}&nbsp;&nbsp;}&nbsp;&nbsp;}&nbsp;&nbsp;/**&nbsp;&nbsp; *&nbsp; Client Invocation &nbsp;&nbsp; */&nbsp; class&nbsp;client&nbsp;{&nbsp;&nbsp;/**&nbsp;&nbsp; *&nbsp;main&nbsp;program.&nbsp;&nbsp; * * &nbsp; Public&nbsp;static&nbsp;function&nbsp;main () &nbsp;{&nbsp;&nbsp; header ("content-type:text/html;&nbsp; Charset=utf-8 ");&nbsp;&nbsp;/*&nbsp; load Customer ID 1 Customer information &nbsp;*/&nbsp; $customer &nbsp;=&nbsp;customer::find (1);&nbsp; &nbsp;/*&nbsp; assume that the user has an order ID of &nbsp;9527*/&nbsp; $customer-&gt;deleteorder (9527);&nbsp;&nbsp;}&nbsp;&nbsp;}&nbsp; &nbsp; CliEnt::main ();&nbsp;&nbsp;?&gt; 

As in the previous article, this is just an example of an active record, and for the application of the active record pattern, you can view the DB class in the Yii framework, which has a Cactiverecord abstract class in its source code, where you can see the application of the active record pattern.

In addition, if you create an activity record from a transaction script, you typically first wrap the table as a portal, and then start the behavior migration to make the table Drill-down into an active record.

You can use the Magic method to __set methods and __get methods for the access and settings of the fields in the active record, as in the Yii framework.

Data source schema mode-Data mapper

One: Data mapper

Relational databases are used to store data and relationships, and objects can handle business logic, so to leelawadee the data itself and the business logic into one object, we either use the activity record or separate the two and associate the two with the data mapper.

The data mapper is the intermediate software layer separating the memory object and the database, and the following sequence diagram describes the concept of the intermediate software layer:

In this sequence diagram, we also see a concept that the mapper needs to be able to get the domain object (in this case, a person is a domain object). As for the changes in the data (or the changes in the domain objects), the Mapper must know these changes, and at this point we need the work unit pattern (after discussion).

From the above, we seem to see the data mapper is quite simple, the complex part is: we need to deal with the table query, domain object inheritance, and so on. The fields of the realm object may come from multiple tables in the database, and we have to let the data mapper do more. Yes, as we mentioned above, the data mapper can do two complex parts:

1: Perceptual change;

2: By the result of the query of the table, assigning value to the domain object;

In order to perceive changes and to be consistent with database objects, you need to identify mappings (schema pattern object and relational structure pattern: Identity field), which typically requires a registry that identifies mappings, or holds an identity map for each lookup method, the following code is the latter:

void Main ()


sqlhelper.connectionstring = "Data source=xxx;initial catalog=xxx;integrated security=false; User Id=sa; password=xxx; Connect timeout=15; Encrypt=false; Trustservercertificate=false ";

var user1 = User.finduser ("6f7ff44435f3412cada61898bcf0df6c");

var user2 = User.finduser ("6f7ff44435f3412cada61898bcf0df6c");

(User1 = = User2). Dump ();

"End". Dump ();


Public abstract class Basemode


public string Id {get; set;}

public string Name {get; set;}


public class User:basemode


Static UserMap map = new UserMap ();

public static User Finduser (string id)


var user = map. Find (ID);

return user;



public class Usermap:abstractmapper&lt;user&gt;


Public User find (string id)


Return (User) abstractfind (ID);


protected override User Abstractfind (string id)


var user = base. Abstractfind (ID);

if (user = null)


' Is Null '. Dump ();

String sql = "SELECT * from [El_organization]." [User] WHERE id= @Id ";

var PMS = new sqlparameter[]


New SqlParameter ("@Id", Id)


var ds = SqlHelper.ExecuteDataset (CommandType.Text, SQL, PMS);

user = Datatablehelper.tolist&lt;user&gt; (ds. Tables[0]). FirstOrDefault ();

if (user = null)


return null;


user = Load (user);

return user;


return user;


Public list&lt;user&gt; findlist (string name)


SELECT * from USER WHERE NAME like name

List&lt;user&gt; users = null;

Return Loadall (users);


public void Update (user user)





Public abstract class abstractmapper&lt;t&gt; where T:basemode


The problem here is that as the object disappears, the Loadedmap is recycled.

Protected Dictionary&lt;string, t&gt; loadedmap = new dictionary&lt;string, t&gt; ();

Protected T Load (T-t)


if (Loadedmap.containskey (


return loadedmap[];




Loadedmap.add (, T);

return t;



Protected list&lt;t&gt; Loadall (list&lt;t&gt; ts)


for (int i=0 i &lt; ts. Count; i++)


Ts[i] = Load (Ts[i]);


return TS;


Protected virtual T Abstractfind (string id)


if (Loadedmap.containskey (ID))


return Loadedmap[id];




return null;




Above is a simple mapper, which has the identity mapping function. Because there is an identity mapping, we run this code to get the result:

Return to the essence of the question: what is called "Data map"

Actually, this is a very important question.

UserMap uses the Find method to turn a database record into a user object, which is called a "data map," but what really plays a central role is the user = Datatablehelper.tolist&lt;user&gt; (ds). Tables[0]).  FirstOrDefault (); This line of code. Further,datatablehelper.tolist&lt;t&gt; This method completes the data mapping function.

So what the,datatablehelper.tolist&lt;t&gt; method does, in fact, is to get the field values of the DataTable based on the property name. This is an easy way to or it might be a good idea in a lot of business-not-complex scenarios, but because the business is often complex, in practice, we don't have much of a way to use this method, and in most cases we need to encode like this to complete the mapping:

Someone. Name = convert.tostring (row["Name")

Do not doubt that the above line of code, called the data map, any tall concept, is actually that you write a lot of code.

Data mapping in 1.1 entityframework

This is a typical EF data mapping class,

public class Coursemap:entitytypeconfiguration&lt;course&gt;


Public Coursemap ()


Primary Key

This. Haskey (t =&gt; T.courseid);


This. Property (T =&gt; T.courseid)

. Hasdatabasegeneratedoption (Databasegeneratedoption.none);

This. Property (T =&gt; t.title)

. IsRequired ()

. Hasmaxlength (100);

Table &amp; Column Mappings

This. ToTable ("Course");

This. Property (t =&gt; T.courseid). Hascolumnname ("CourseID");

This. Property (t =&gt; t.title). Hascolumnname ("Title");

This. Property (t =&gt; t.credits). Hascolumnname ("credits");

This. Property (t =&gt; T.departmentid). Hascolumnname ("DepartmentID");


This. Hasmany (T =&gt; t.people)

. Withmany (T =&gt;

. Map (M =&gt;


M.totable ("Courseinstructor");

M.mapleftkey ("CourseID");

M.maprightkey ("PersonID");


This. Hasrequired (T =&gt; t.department)

. Withmany (T =&gt;

. Hasforeignkey (d =&gt; D.departmentid);



We can see that the EF data map, that's the real data map. The most basic thing in the house is to do one of these things:

Which field the database is, and which property is the property of the corresponding memory object.

Ultimately, it generates domain models through an object factory, and the principle is as follows:

Internal static Course Buildcourse (IDataReader Reader)


Course Course = new Course (Reader[fieldnames.courseid]);

Contract. Title = Reader[fieldnames.title]. ToString ();


return contract;


Second: storage storehouse

UserMap is the concept of a data mapper too heavy? Because it does the mapping and persistence thing, it even has to hold a unit of work. So, if we can be like the EF, the mapper only does the mapping, and the rest of the things? OK, this part of the separation is called the storehouse.

Three: Say a little more datatablehelper.tolist<t> simplified data mapper

It's actually the DataTable to List. If you are using a framework such as EF or NHibernate, then use the mapper that they provide (strictly speaking, you are not using their mapper.) Because the frameworks themselves are using their own mapper, we are only configuring the data and relationships that the mapper needs, sometimes these configurations are in the configuration file, sometimes on the field or attribute, and sometimes on a simple but large line of code. We can of course create our own standard mapper, which is implemented by Tim McCarthy in the domain driven design C # 2008 implementation. However, EF and NHibernate are good, but many times we still have to use handwritten SQL because:

1:ef and NHibernate are required to learn cost, which represents the high cost of team training, and error-prone;

2: The efficiency of handwriting SQL should not be discarded.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.