Question: Write a database operation class TDBOPERATE_DL, unify the operation of the database. Provide a statement of statement of statements, submit transactions, and rollback transactions for other class calls.
TDBOPERATE_DL = Class
Private
Adoc: tadoconnection;
Adoq: tadoquery;
Isdestroyadoc: boolean; / / Do you destroy your own adoc?
Fisintrans: boolean; // Whether you have started
public
ISCommit: boolean; // Do you want to submit a transaction, the default is true, if there is a class vote, it is subject to submission.
Function isintrans: boolean;
Constructor Create (Const Newadoc: tadoconnection); overload;
Constructor Create (Const ServerName, DatabaseName, UserId, Password: String); OVERLOAD
DESTRUCTOR DESTROY; OVERRIDE;
Procedure begintrans;
Procedure committrans;
Procedure rollbacktrans;
Procedure Execute (const Sqlstring: String);
Function getDataSet (const Sqlstring: String): _ recordset;
Function GetConnection: Tadoconnection;
Procedure setConnection (Const Newadoc: tadoconnection);
END;
Some functions:
Procedure TDBOPERATE_DL.BEGINTRANS; // Start transaction
Begin
Self.adoc.begintrans;
Self.fisintrans: = TRUE;
END;
Procedure TDBOPERATE_DL.COMMITTRANS; / / Submit a transaction
Begin
Self.adoc.committrans;
Self.fisintrans: = false;
END;
Procedure TDBOPERATE_DL.ROLLBACKTRANS; / / Rolling Transaction
Begin
Self.adoc.rollbacktrans;
Self.fisintrans: = false;
END;
Function TDBOPERATE_DL.IsInTrans: boolean; / / View business has started
Begin
Result: = Self.fisintrans;
END;
Write a TTHING class that is used to add, modify, or delete records about something about something, call the TDBOPERATE_DL class. In order to call convenience, the relevant transaction is placed in the TTHING class, and the external call does not need to consider the transaction.
Such as:
Procedure TTHING.DROP (Const Thing: String);
VAR
SQLSTRING: STRING;
Begin
SQLSTRING: = Deleted SQL statement;
Self.dboprate.begintrans; // DBOPERATE is a private variable of TDBOPERATE_DL type to create a TTHING class instance.
Try
Self.dboperate.execute (sqlstring);
Self.dboprate.committrans;
Except
Self. dboprate.rollbacktrans; raise;
END;
END;
Later, I wrote a TPERSON class to add, modify, or delete the records of someone in the database. The same transaction is in the TPERSON class. Now I want to delete the people's records, when calling TTHING classes and people related things, the transaction problem appears: transaction can't nest. If you first delete Thes, re-declare transactions delete TPERSON, if TPERSON is wrong, what happens to roll thes?
Such as:
Procedure TPERSON.DROP (Const Person: String);
VAR
SQLSTRING: STRING;
TTHING;
Begin
SQLSTRING: = Deleted SQL statement;
"= TTHING.CREATE (Self.dbope); // TDBOPERATE_DL type DBOPERATE is passed as a parameter.
Self.dboprate.begintrans;
Try
Thing.drop (Person); // There is a transaction in the above code
Self.dboperate.execute (sqlstring);
Self.dboprate.committrans;
Except
Self.dboprate.rollbacktrans;
Raise;
END;
END;
Solution, two-stage submission, first sticky point background knowledge:
Regardless of the two or three-layer system, things are implemented through two phases. In the first phase, each executed resource / record is written in a transcation context, then the resource coordinator sequentially queries whether the implementation of each participating matter is successful. If there is no problem, enter the second phase. Each execution has started its operation. If there is a problem with a problem, the resource coordinator notifies all subordinates to abandon the COMMIT and restore the data.
Refer to Com 's transaction, if a component is required, the transaction has begun when the component is created, and transaction votes when the component is destroyed. If it is a root transaction, submit or rollback transactions. (If the component supports poolization, these two situations occur in component activation and sleep events). So we define a class as follows.
// The ancestral class of the business class is used to provide unified transaction support.
TTS_DL = Class
Private
Isroottrans: boolean; // is the root transaction
IsNeedTrans: boolean; / / Do you need a transaction
public
DBOPERATE: TDBOPERATE_DL; // Example of the class of the database
Procedure setcomplete;
Procedure setAbort;
Constructor Create: TDBOPERATE_DL; NeedTrans: Boolean; // Do you need transaction support
DESTRUCTOR DESTROY; OVERRIDE;
END;
In this class, in addition to the instance of the class that passes the operation database, it is incremented by a mark that requires a transaction, because if it is only the operation of reading the database, it is not necessary.
Class implementation code is as follows:
Constructor TTS_DL.CREATE (Const NewDbopide: TDBOPERATE_DL;
NeedTrans: boolean;
Begin
Inherited Create;
Self.dboprate: = newdboprate; self.isneedtrans: = nesedTrans; // Assignment requires transaction
IF self.isneedtrans the
Begin
// If you are in a transaction, it is not an root transaction, and the value of IsCommit is unchanged in the transaction.
IF self.dboprate.isintrans then
SELF.ISROOTTRANS: = FALSE
Else
Begin
Self.dboprate.begintrans; // is a root transaction, starting business
SELF.ISROOTTRANS: = TRUE
Self.dboprate.isCommit: = true; // Initialization Submit Sign is to submit a transaction
END;
END;
END;
DESTRUCTOR TTS_DL.DESTROY;
Begin
IF self.isneedtrans the
Begin
// If it is a root transaction, you will follow the results of the voting or rollback.
IF self.isroottrans thein
Begin
IF self.dboprate.iscommit kil
Self.dboprate.committrans
Else
Self.dboprate.rollbacktrans;
END;
END;
inherited;
END;
Procedure tts_dl.setabort;
Begin
Self.dboprate.isCommit: = Self.dboprate.iscommit and false; // Vote says rollback
END;
Procedure TTS_DL.SETCOMPLETE;
Begin
Self.dboprate.iscommit: = self.dboprate.iscommit and true; // Vote said to be submitted
END;
Back to the business class TTHING and TPERSON, this time is inherited from the TTS_DL class.
TTHING = Class (TTS_DL);
TPERSON = Class (TTS_DL);
The TTHING delete code should be as follows:
Procedure TTHING.DROP (Const Thing: String);
VAR
SQLSTRING: STRING;
Begin
SQLSTRING: = Deleted SQL statement;
Try
Self. dboprate.execute (sqlstring);
Self. dboprate.setcomplete; // vote
Except
Self. dboprate.setAbort; // Vote rollback
Raise;
END;
END;
The deletion code of TPERSON is as follows:
Procedure TPERSON.DROP (Const Person: String);
VAR
SQLSTRING: STRING;
TTHING;
Begin
SQLSTRING: = Deleted SQL statement;
= TTHING.CREATE (Self. Dboprate, true); // tdboprate_dl type DBOPERATE DBOPERATE as a parameter, TRUE represents a transaction.
Try
Try
Thing.drop (Person);
Self.dboperate.execute (sqlstring);
Self.dboprate.setComplete; // Voted Submit
Except
Self. dboprate.setAbort; // Vote Roll Raise;
END;
Finally
Thing.Free; // Remember to release
END;
END;
Remember the use of the unique operation database class TDBOPERATE_DL in the main program to record the release business class instance, if it is required, try to release, OK, and get it.
The first version, limited horizontal, but also need to be improved in practical applications, all of which is throwing bricks, please have experienced heroes :)