Two-stage submission with Delphi analog components

zhaozj2021-02-17  76

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 :)

转载请注明原文地址:https://www.9cbs.com/read-31219.html

New Post(0)