Skip to content

connection.BeginTransaction cause memory leak #816

@wzl-bxg

Description

@wzl-bxg

Hello, when using connection.BeginTransaction, the below code will cause memory leak:

public static ICapTransaction BeginTransaction(this IDbConnection dbConnection, ICapPublisher publisher, bool autoCommit = false)
{
    if (dbConnection.State == ConnectionState.Closed)
    {
        dbConnection.Open();
    }

    var dbTransaction = dbConnection.BeginTransaction();
    publisher.Transaction.Value = publisher.ServiceProvider.GetService<ICapTransaction>();
    return publisher.Transaction.Value.Begin(dbTransaction, autoCommit);
}

ICapPublisher is registered as singleton, ICapTransaction is registered as transient; you create transient object(ICapTransaction) by singleton object(ServiceProvider), and the transient object(ICapTransaction) implements IDisposable, so the transient object(ICapTransaction) will never GC because the IOC container is not released.

I simulate 100000+ calls to the action AdonetWithTransaction, see the below code:

[Route("~/adonet/transaction")]
public IActionResult AdonetWithTransaction()
{
using (var connection = new MySqlConnection(AppDbContext.ConnectionString))
{
    using (var transaction = connection.BeginTransaction(_capBus, true))
    {
        //your business code
    }
}

return Ok();
}

Then I turn on VS diagnostics tools to monitor memory changes, I found the objects that inherit ICapTransaction will persist in memory,see below:
memory_leak_issue

You can use ActivatorUtilities.GetServiceOrCreateInstance to create transient object(ICapTransaction) in method connection.BeginTransaction

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions