Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the general connection and transaction management method of ASP.NET

2025-01-15 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly explains "what is the general connection and transaction management method of ASP.NET". The content of the explanation is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "what is the general connection and transaction management method of ASP.NET".

General connection and transaction management methods

Connection and transaction management is one of the most important concepts for applications that use databases. When you open a database connection, when to start the transaction and how to release the connection. Things like that.

As you all know, .net uses connection pooling (connection pooling). Therefore, creating a connection is actually getting a connection from the connection pool, which is done because of the cost of creating a new connection. If no connections exist in the connection pool, a new connection object is created and added to the connection pool. When you release the connection, it actually sends the connection object back to the connection pool. This is not a practical release. This mechanism is provided by .net. Therefore, we should release the connection object after using it. This is the best practice.

In an application, there are two common parties to create / release a database connection:

The first method: create a connection object when the Web request arrives. (Application_BeginRequest, the event in global.asax), uses the same connection object to handle all database operations, and closes / releases the connection at the end of the request (Application_EndRequest event).

This is a simple but inefficient method for the following reasons:

Maybe the Web request does not need to manipulate the database, but the connection will be opened. This is an inefficient use of connection pooling.

This may make Web requests take longer to run, and database operations may require some execution. This is also an inefficient way to use connection pooling.

This is feasible for Web applications. If your application is Widnows Service, this may not be possible.

Again, this is the best scenario for using transactional database operations. If one operation fails, all operations are rolled back. Because the transaction locks some data columns (event data tables) in the database, it must be short-lived.

The second method: create a connection when needed (as long as before using it) and release it after using it. This is quite efficient, but it has to be done tediously and repeatedly (create / release connections).

Connection and transaction Management of ABP

ABP integrates the above two methods of connection management and provides a simple and efficient model.

Warehousing (Repository classes)

Warehousing is the main class of database operations. ABP opens a database connection and enables a transaction when entering the warehousing method. Therefore, you can safely use the connection in the warehousing method. At the end of the warehousing method, the transaction is committed and the connection is released. If the warehousing method throws any exceptions, the transaction is rolled back and the connection is released. In this mode, the warehousing method is unitary (a unit of work unit of work). ABP is fully automatic in dealing with the above actions. Here, there is a simple repository:

Public class ContentRepository: NhRepositoryBase, IContentRepository {public List GetActiveContents (string searchCondition) {var query = from content in Session.Query () where content.IsActive & &! content.IsDeleted select content; if (string.IsNullOrEmpty (searchCondition)) {query = query.Where (content = > content.Text.Contains (searchCondition));} return query.ToList ();}}

This example uses NHibernate as the ORM framework. As shown above, there is no need to write any program code for database connection operations (Session in NHibernate).

If the warehousing method calls another warehousing method (generally speaking, if the work unit method invokes the method of another unit of work), they all use the same connection and transaction. The first warehouse method called is responsible for managing connections and transactions, while the rest of the warehouse methods invoked by it are simply used without management.

Application Services (Application service classes)

A method of applying services is also considered to use units of work. If we have an application service method as follows:

Public class PersonAppService: IPersonAppService {private readonly IPersonRepository _ personRepository; private readonly IStatisticsRepository _ statisticsRepository; public PersonAppService (IPersonRepository personRepository, IStatisticsRepository statisticsRepository) {_ personRepository = personRepository; _ statisticsRepository = statisticsRepository;} public void CreatePerson (CreatePersonInput input) {var person = new Person {Name = input.Name, EmailAddress = input.EmailAddress}; _ personRepository.Insert (person); _ statisticsRepository.IncrementPeopleCount ();}}

In the CreatePerson method, we add a person that uses person warehousing and uses statistics warehousing to increase the total number of people. Two repositories share the same connection and transaction in this example, because this is an application service approach. ABP opens a database connection and opens a transaction when entering the CreationPerson method, if no exception is thrown, and then commits the transaction at the end of the method. If any exception is thrown, the transaction will be rolled back. Under this mechanism, all database operations become unit (unit of work) in CreatePerson.

Unit of work (Unit of work)

The work unit works in the background for warehousing and application service methods. If you want to control database connections and transactions, you need to manipulate the unit of work directly. Here are two examples of direct use:

The first and best way to use UnitOfWorkAttribute is as follows:

[UnitOfWork] public void CreatePerson (CreatePersonInput input) {var person = new Person {Name = input.Name, EmailAddress = input.EmailAddress}; _ personRepository.Insert (person); _ statisticsRepository.IncrementPeopleCount ();}

Therefore, the CreatePerson method is transformed into a unit of work and manages database connections and transactions, and both warehousing objects use the same unit of work. Note that if this is the method of applying the service, you do not need to add the UnitOfWork attribute, see Unit of work method: chapter 3, 3.3.5.

The second example is the use of IUnitOfWorkManager.Begin (...) The method is as follows:

Public class MyService {private readonly IUnitOfWorkManager _ unitOfWorkManager; private readonly IPersonRepository _ personRepository; private readonly IStatisticsRepository _ statisticsRepository; public MyService (IUnitOfWorkManager unitOfWorkManager, IPersonRepository personRepository, IStatisticsRepository statisticsRepository) {_ unitOfWorkManager = unitOfWorkManager; _ personRepository = personRepository; _ statisticsRepository = statisticsRepository;} public void CreatePerson (CreatePersonInput input) {var person = new Person {Name = input.Name, EmailAddress = input.EmailAddress} Using (var unitOfWork = _ unitOfWorkManager.Begin ()) {_ personRepository.Insert (person); _ statisticsRepository.IncrementPeopleCount (); unitOfWork.Complete ();}

You can inject and use IUnitOfWorkManager, as shown above. As a result, you can create more limited scope units of work. In this mechanism, you can usually call the Complete method manually. If you do not call, the transaction will be rolled back and all exceptions will not be saved. The Begin method is overridden to set options for the unit of work.

This is great, but unless you have a good reason, use the UnitOfWork attribute less.

Unit of work disabled unit of work (Disabling unit of work)

You may want to disable the unit of work that applies the service method (because it is enabled by default). To do this, use the IsDisabled property of UnitOfWorkAttribute. Examples are as follows:

[UnitOfWork (IsDisabled = true)] public virtual void RemoveFriendship (RemoveFriendshipInput input) {_ friendshipRepository.Delete (input.Id);}

Normally, you don't need to do this because the method of applying the service should be monolithic and usually use a database. In some cases, you may want to disable the unit of work of the application service:

Your method does not require any database operations and you do not want to open unwanted database connections

You want to use the unit of work within the limited scope of the UnitOfWorkScope class, as described above

Note that if the unit of work method calls this RemoveFriendship method, disabling it is ignored and it uses the same unit of work as the method that called it. Therefore, you should be very careful when using this feature. Similarly, the above program code works well because the warehousing method is the unit of work by default.

Transactional unit of work (Non-transactional unit of work)

The unit of work is transactional by default (this is its nature). Therefore, ABP starts / commits / rolls back an explicit database-level transaction. In some special cases, the transaction may cause problems because it may lock some data columns or tables in the database. In these situations, you may want to disable database-level transactions. The UnitOfWork property can get a Boolean value from its constructor to make it work like a non-transactional unit of work. Examples are:

[UnitOfWork (false)] public GetTasksOutput GetTasks (GetTasksInput input) {var tasks = _ taskRepository.GetAllWithPeople (input.AssignedPersonId, input.State); return new GetTasksOutput {Tasks = Mapper.Map (tasks)};

It is recommended to do this [UnitOfWork (isTransaction:false)]. (readable and clear).

Note that ORM frameworks such as NHibernate and EntityFramework store data internally in a single command. Suppose you update some entities to non-transactional UoW. Even in this situation, all updates are done at the end of the work unit of a single database command. However, if you execute the SQL query directly, it will be executed immediately.

There is a limitation of non-transactional UoW. If you are already in the transactional UoW area, setting isTransactional to false will be ignored.

Be careful when using non-transactional UoW, because in most cases, data consolidation should be transactional. If your method only reads the data and does not change the data, then of course you can use non-transactionality.

Unit of work calls other units of work (A unit of work method calls another)

If a unit of work method (a method tagged with the UnitOfWork attribute) calls another unit of work method, they share the same connection and transaction. The first method manages the connection, and the other methods simply use it. This is possible if all methods are executed under the same thread (or within the same Web request). In fact, when the unit of work area starts, all program code executes and shares the same connection transaction in the same thread until the unit of work area terminates. This is the same for using both the UnitOfWork property and the UnitOfWorkScope class. If you create a different thread / task, it uses its own unit of work.

Automated saving changes (Automatically saving changes)

When we use a unit of work on a method, ABP automatically stores all changes at the end of the method. Suppose we need a method that updates the person name:

[UnitOfWork] public void UpdateName (UpdateNameInput input) {var person = _ personRepository.Get (input.PersonId); person.Name = input.NewName;}

In this way, the name was changed! We didn't even call the _ personRepository.Update method. The ORM framework continuously tracks all changes in the entity within the unit of work and reflects all changes to the database.

Note that there is no need to declare UnitOfWork in the application service, because they adopt the unit of work by default.

GetAll () method of warehousing interface (IRepository.GetAll ())

When you call the GetAll method outside the repository method, there must be an open database connection because it returns an object of type IQueryable. This is required because the execution of IQueryable is delayed. It does not immediately execute the database query until you call the ToList () method or use IQueryable in the foreach loop (or if you access the queried result set). Therefore, when you call the ToList () method, the database connection must be enabled. Example:

[UnitOfWork] public SearchPeopleOutput SearchPeople (SearchPeopleInput input) {/ / Get IQueryablevar query = _ personRepository.GetAll (); / / Add some filters if selectedif (! 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 listvar people = query.Skip (input.SkipCount) .Take (input.MaxResultCount). ToList (); return new SearchPeopleOutput {People = Mapper.Map (people)};}

Here, the SearchPeople method must be a unit of work, because IQueryable is called when the ToList () method is within the method ontology, and the database connection must be opened when IQueryable.ToList () is executed.

Like the GetAll () method, you have to use a unit of work if you need a database connection and there is no warehouse. Note that the application service method is the unit of work by default.

Restrictions on unit of work attributes (UnitOfWork attribute restrictions)

You can use the UnitOfWork attribute tag in the following situations:

Class all interface-based methods such as public or public virtual (for example, application services are based on service interfaces)

Public virtual methods of self-injection classes (such as MVC Controller and Web API Controller)

All protected virtual methods.

It is recommended that the method be marked as virtual. You cannot apply it to the private method. Because ABP is implemented using dynamic proxy, private methods cannot be implemented using inherited methods. When you do not use dependency injection and initialize the class yourself, the UnitOfWork property (and any proxies) will not work properly.

Option

There are many options that can be used to control the unit of work.

First, we can change all default values for all units of work in startup configuration. This is usually done using the PreInitialize method in our module.

Public class SimpleTaskSystemCoreModule: AbpModule {public override void PreInitialize () {Configuration.UnitOfWork.IsolationLevel = IsolationLevel.ReadCommitted; Configuration.UnitOfWork.Timeout = TimeSpan.FromMinutes (30);} /... other module methods} method

The operation of the work unit system is seamless and invisible. However, in some special cases, you need to call its methods.

SaveChanges

ABP stores all the changes at the end of the unit of work, and you don't have to do anything. However, sometimes you may want to store all the changes in the process of the unit of work. In this case, you can inject IUnitOfWorkManager and call the IUnitOfWorkManager.Current.SaveChanges () method. In the example, Entity Framework gets the Id of the new entity when storing changes. Note that the current unit of work is transactional, and all changes in the transaction are rolled back when an exception occurs, even if SaveChange has been called.

Event

The unit of work has a Completed/Failed/Disposed event. You can register these events and do what you want. Inject IUnitOfWorkManager and use the IUnitOfWorkManager.Current attribute to get the currently active unit of work and register its events.

You may want to execute some program code that is successfully completed in the current unit of work. Example:

Public void CreateTask (CreateTaskInput input) {var task = new Task {Description = input.Description}; if (input.AssignedPersonId.HasValue) {task.AssignedPersonId = input.AssignedPersonId.Value; _ unitOfWorkManager.Current.Completed + = (sender, args) = > {/ * TODO: Send email to assigned person * /};} _ taskRepository.Insert (task) } Thank you for your reading. The above is the content of "what is the general connection and transaction management method of ASP.NET". After the study of this article, I believe you have a deeper understanding of what the general connection and transaction management method of ASP.NET is, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report