Written by 15:03 ASP .NET CORE, Languages & Coding

Resource Release in .NET Applications

In C#, there is one huge benefit, which is a drawback at the same time – an automatic garbage collection. With traditional desktop applications, this is great when a platform cleans up the whole garbage and releases memory. However, it is not always good for Web.

When we develop a Web application, Web-requests are mainly short; our code must perform small tasks and work very quickly. If we do not help a garbage collector, the server resources can exhaust in no time.

The first one what fails is connections to MS SQL Server. In .NET, we can establish SqlConnection, open it and not close it because .NET garbage collector will do this for us. I have seen a Web code for several times when programmers did the same thing. The fact is that they open a connection in one place and use it in another one. In order not to open the connection twice per one request, they open it at the beginning and do not close it hoping that .NET will do this for us.

We established the connection to the database:

public ActionResult Index() 
{
  SqlConnection connection = new SqlConnection();
  connection.ConnectionString = "connection string";
  connection.Open();
  
  . . .
  . . .

  return View();
}

The question is when the connection to the database will be closed. Yes, it will be closed automatically and we do not need to care about the resources. However, when will these resources be released? We do not know. After running the code, the connection will still be open and busy. The actual release of resources may occur in a minute or five. It means that there will be a bunch of open resources on the server forbidden to be used. The number of simultaneously available connections is not limitless on the server. Everything depends on the settings and when you reach the maximum, it will be impossible to open a new connection and the site will be down until the garbage collector releases the unused connections.

Please note that open and busy connections are different things. Let’s take a look at the connection lifetime. When you first open (call the Open method) the SqlConnection object, .NET performs the following steps:

  • allocates necessary resources to the object
  • creates a connection to the database

The connection is open and reserved for your object. When you implement the Close or Dispose methods, the SqlConnection object is removed in .NET, and the connection is open in a special pool for a while. The connection is still open to be used and linked to any other object of SqlConnection.

Now, if you try to open a new SqlConnection object, .NET will scan the pool to find any open connections with the same connection string. Provided that they exist, a new object will be created, however, a new physical connection to the server will not be established. Instead, an existing connection from the pool will be used. Thus, this saves time for exchanging welcome messages with the database, and the SqlConnection object is available for use instantly.

I maintain the site with millions of users and the number of simultaneous and open connections to the database does not exceed 600 even at rush hours. Outside of rush hours, there are 200 connections. Recently, we have launched a small update and the number of connections increased to 1500 outside of rush hours, while during rush hours the site was down due to the lack of free space in the pool. We saw this bug just when the site was down because the number of connections was insufficient. After the update, we did not check how many open connections there are.

The bug was in the code when the connection was opened, however, it was not closed explicitly. Since the resources were not released in time, we lost them. When I found this bug and fixed it, the number of connections reduced from 1000 to 200.

When developing Web applications, always apply the using construction to open resources:

public ActionResult Index() 
{
  using (SqlConnection connection = new SqlConnection())
  {
   connection.ConnectionString = "connection string";
   connection.Open();
  
   . . .
   . . .
  }

  return View();
}

In this case, .NET knows that we need a connection only for some time, while we are using this block. As soon as we go beyond this block, the platform can see that this resource is not needed anymore and can be released. In this case, we know for sure (if Microsoft programmers do not mess up) that the connection to the database will be closed immediately after leaving the using block. You do not have to call the Close method explicitly, simply apply using.

Garbage collector works great in .NET. The main point is to use it correctly and help the platform to identify when resources are no longer needed. Then, it will take care of everything.

What about the case when you need to use the connection in different places of the program to perform two different requests in two various places? If using cannot encompass both codes (they are located in different methods), then you should not even try to seize the unseizable. Create two SqlConnection objects and open the connection twice. This is not a problem for the server because it can use Connection Pool. After closing the first connection, it will not be actually closed. The object will be deleted and the connection will be marked as free. For some time (it’s easy to configure this), the connection will remain open and when creating the next SqlConnection object, you do not have to spend time on establishing a connection to the server. You can use the one already opened from the pool.

In this article, I use the database connection as the most popular resource type for similar applications. The same can be done with files and anything that has the Close method. You do not have to close it yourself, though, explicitly closing the connection is a sign of good manners. However, if you do not want to close it yourself, at least apply the using block.

Save your resources, especially, if your applications are running on shared hosting. If you do not care that your site may be suspended due to lack of connections to the server, think at least about neighboring sites that use the same database.

Tags: , Last modified: September 22, 2021
Close