<<ABP Frame >> Work unit

Source: Internet
Author: User

Document Directory

The content of this section:

    • Brief introduction
    • Managing connections and transactions in the ABP
      • Agreed unit of work
        • Unitofwork characteristics
        • Iunitofworkmanager
    • Work Unit Details
      • Disabling work cells
      • Non-transactional unit of work
      • The work cell method calls another method
      • Work Cell Field
      • Automatically save changes
      • Irepository.getall () method
      • Unitofwork restrictions
    • Options
    • Method
      • SaveChanges
    • Event

Brief introduction

In an application that uses a database, connections and transactions are important, when a connection is opened, when a transaction is started, if the connection is released, and so on. ABP manages the connections and transactions of a database through a unit of work system.

Managing connections and transactions in the ABP

When a unit of work method is used, the ABP opens a database connection (which may not be opened immediately, opens the first time the database is used, depends on the implementation of the ORM provider) and begins a transaction, so you can safely use the connection within this method, at the end of this method, commit the transaction and release the connection, If this method throws any exceptions, rollback the transaction and release the connection, in this way, a unit of work is atomic. The ABP automatically completes these operations.

If a unit of work method invokes another unit of work method, both use the same connection and transaction, the first method manages the connection and the transaction, and the other uses them.

Agreed unit of work methods

Some methods default to the unit of work Method:

    • Actions for all MVC, Web APIs, and ASP. NET Core MVC controllers.
    • All application service methods.
    • All warehousing methods.

Let's say we have an application service approach, as follows:

 Public classpersonappservice:ipersonappservice{Private ReadOnlyipersonrepository _personrepository; Private ReadOnlyistatisticsrepository _statisticsrepository;  PublicPersonappservice (ipersonrepository personrepository, istatisticsrepository statisticsrepository) {_personR Epository=personrepository; _statisticsrepository=statisticsrepository; }     Public voidCreateperson (Createpersoninput input) {varperson =Newperson {Name = input. Name, EmailAddress =input.        EmailAddress};        _personrepository.insert (person);    _statisticsrepository.incrementpeoplecount (); }}

In the Createperson method, we use personnel warehousing to insert a person, and use statistical warehousing to increment the total number of people, both of which share the same connection and transaction, because the application service method defaults to a unit of work. When entering the Createperson method, the ABP opens a connection and begins a transaction, at the end of the method, if no exception occurs, commits the transaction and releases the connection, in this way, all database operations, in the Createperson method, become atomic.

Control unit of work

In the above method, the working unit is secretly working. In most cases of Web applications, we don't have to control the unit of work. If you want to control the unit of work in some places, you can use it explicitly, there are two ways to do it.

Unitofwork characteristics

The preferred method is to use the Unitofwork feature, for example:

[Unitofwork]  Public void Createperson (Createpersoninput input) {    varnew person {Name = input. Name, EmailAddress = input. EmailAddress};    _personrepository.insert (person);    _statisticsrepository.incrementpeoplecount ();}

Therefore, the Createperson method becomes a unit of work, managing database connections and transactions, two warehouses using the same unit of work, and note that if you are in an application service method, you do not need to use the Unitofwork feature. Also See ' Unit of Work Method restrictions ' section.

Unitofwork features some options, refer to "Working unit details" below.

Iunitofworkmanager

The second method is: Use Iunitofworkmanager.begin (...) method, as follows:

 Public classmyservice{Private ReadOnlyIunitofworkmanager _unitofworkmanager; Private ReadOnlyipersonrepository _personrepository; Private ReadOnlyistatisticsrepository _statisticsrepository;  PublicMyService (Iunitofworkmanager unitofworkmanager, IPersonRepository personrepository, IStatisticsRepository Statisticsrepository) {_unitofworkmanager=Unitofworkmanager; _personrepository=personrepository; _statisticsrepository=statisticsrepository; }     Public voidCreateperson (Createpersoninput input) {varperson =Newperson {Name = input. Name, EmailAddress =input.        EmailAddress}; using(varUnitofwork = _unitofworkmanager.begin ())            {_personrepository.insert (person);            _statisticsrepository.incrementpeoplecount ();        Unitofwork.complete (); }    }}

As shown above, you can map and use Iunitofworkmanager (some base classes are already injected by default into UNITOFWORKMANAGER:MVC controllers, app services, Domain Services, and so on), so you can create more domain-constrained units of work. In this way, you should call the complete method manually, and if you do not call, the transaction will be rolled back and the modification will not be saved.

The Begin method has several overloads for setting the unit of work option, and it is best to use the Unitofwork attribute if there is no good reason.

Work Unit Details

Disabling work cells

If you want to disable work cells for the agreed work cell method, use the Isdisabled property of the Unitofwork attribute. For example:

true )]publicvirtualvoid  removefriendship (removefriendshipinput Input) {    _friendshiprepository.delete (input. ID);}

Normally, you don't want to do this, but in some cases you need to disable the unit of work:

    • You may want to restrict the domain of the unit of work, as described above, using Unitofworkscope.

Note: If a unit of work method calls this Removefriendship method, the disabled attribute is ignored and the method uses the same unit of work as the caller method. So be careful with disabling features. Similarly, the code above will work well, as the warehousing method defaults to a unit of work.

Non-transactional unit of work

A unit of work is transactional by default, so the ABP starts/commits/rolls back database-level transactions. In some special cases, a transaction can cause problems because it may lock some rows or tables in the database. In this case, you may want to disable database-level transactions. The Unitofwork attribute can be used in its constructor to obtain a Boolean value as a non-transactional identity. Examples of Use:

false )]public  gettasksoutput gettasks (gettasksinput input) {    var tasks = _taskrepository.getallwithpeople (input. Assignedpersonid, input. State);     return New Gettasksoutput            {                = mapper.map<list<taskdto>>(tasks)            };}

I suggest [Unitofwork (Istransactional:false)] To use this feature, which I think is more readable and clearer. But you can also use [Unitofwork (false)].

Note: The ORM frameworks, such as NHibernate and entityframework, use a separate command to save the changes. Suppose you update some entities in a non-transactional unit of work, and even in this case, all updates are executed at the end of the unit of work, executing a separate database command. However, if you execute an SQL statement directly in a non-transactional unit of work, it will be executed directly and will not be rolled back.

A non-transactional unit of work has a limit, and if you are already in a transactional work cell domain, setting IsTransactional to False is also ignored (in a transactional unit of work, a non-transactional unit of work is created using the transaction Domain option).

Use a non-transactional unit of work with caution, because in most cases data integrity should be guaranteed with transactional. If you just read the data without making changes, you can safely use non-transactional.

One unit of work method calls another method

The work cell is rounded, and if one unit of work method calls another unit of work method, they share the same connection and transaction, the first method manages the connection and the transaction, and the other method uses them.

Work Cell Field

You can create another independent transaction in one transaction, or create a non-transactional domain in a transaction. NET defines the transactionscopeoption for it. You can control it by setting the Work cell domain option.

Automatically save changes

If a method is a unit of work, the ABP automatically saves all modifications at the end of the method. Suppose we need a way to update the name of the person:

[Unitofwork]  Public void updatename (Updatenameinput input) {    var person = _personrepository.get (input. PERSONID);      =   input. NewName;}

This is all code, name will be modified! We don't even have to call the _personrepository.update method. In a unit of work, the ORM framework tracks all changes to the entity and reflects it to the database.

Note: You do not need to declare unitofwork for a contract work cell method.

Irepository.getall () method

When you use GetAll () in a warehouse method, it must have an open database connection because it simply returns IQueryable. This is necessary because of the delayed execution of the iquery. It does not perform database queries unless you call ToList () or use IQueryable in a Foreach loop (or access the items in the query in some way), so when you call the ToList () method, the database connection must be available.

Consider the following example:

[Unitofwork] Publicsearchpeopleoutput searchpeople (searchpeopleinput input) {//Get iqueryable<person>    varquery =_personrepository.getall ();    //Add Some filters if selected    if(!string. IsNullOrEmpty (input. Searchedname)) {query= Query. Where (person =Person . Name.startswith (input.    Searchedname)); }    if(input. Isactive.hasvalue) {Query= Query. Where (person = = person. IsActive = =input.    Isactive.value); }    //Get paged Result list    varPeople =query. Skip (input. Skipcount). Take (input. Maxresultcount).    ToList (); return Newsearchpeopleoutput {people = mapper.map<list<persondto>>(People)};}

The Searchpeople method must be a unit of work, because the IQueryable ToList () method is called in this method. And when Iqueryable.tolist () is executed, the database connection must be open.

In most cases, it is safe to use the GetAll method in a Web application because the control action is the work unit by default and the database connection is available throughout the request.

Unitofwrok Feature Limitations

You can use Unitofwork as:

    • All public or public virtual of a class and uses methods on top of the interface (such as an application service is used on the interface).
    • All public virtual and self-injected methods of the class (such as the MVC controller and the Web API controller).
    • All protected virtual methods.

It is recommended that you always use the virtual method, which you can not do for private methods, because the ABP uses dynamic proxies for them, and the private method is invisible to the class that inherits it. If you do not use dependency injection and instantiate this class yourself, the Unitofwork attribute (and any proxy) will not work.

Options

Some options can change the behavior of a unit of work.

First, we can modify the default values for all work units in the launch configuration, usually in the pre-initialization method of our module.

 Public class simpletasksystemcoremodule:abpmodule{    publicoverride void  Preinitialize ()    {        = isolationlevel.readcommitted;         = Timespan.fromminutes (+);    }     // ... other module methods}

Second, we can override the default values for a particular unit of work, and for this reason, the Unitofwork attribute constructor and the Iunitofworkmanager.begin method have overloads to get the options.

Finally, you can configure the work cell attribute defaults (view their respective documents) for ASP. NET MVC, Web API, and ASP. NET Core MVC controllers by launching the configuration.

Method

The unitofwork system works silently and seamlessly, but in some special cases, you need to call them in a way.

You can access the current unit of work in one of the following ways:

    • If your class inherits from some special base classes (Applicationservice, Abpcontroller, Abpapicontroller, etc.), you can use the Currentunitofwork property directly.
    • You can inject iunitofworkmanager into any class and then use the Iunitofworkmanager.current property.

SaveChanges

ABP at the end of a unit of work, save all the changes, you don't have to do anything, but sometimes you want to save changes to the database in the middle of a work cell operation, such as in EntityFramework, to get the ID of the new entity, save it first.

You can use the SaveChanges or Savechangesasync method of the current work cell.

Note: If the current unit of work is transactional, all modifications are rolled back in the event of an exception, otherwise saved.

Event

A unit of work has completed, failed, and disposed events, and you can register these events and perform the required actions. For example, you want to run some code after the current unit of work has completed successfully:

 Public void createtask (Createtaskinput input) {    varnew Task {Description = input. Description};     if (input. Assignedpersonid.hasvalue)    {        = input. Assignedpersonid.value;        _unitofworkmanager.current.completed  /* */ };    }    _taskrepository.insert (Task);}

<<ABP Frame >> Work unit

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: info-contact@alibabacloud.com 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.