Попытка понять ошибочное поведение DB Connection, используемого Dapper

Мне нужна помощь, чтобы лучше понять, как Dapper обрабатывает соединения с БД и почему должным образом не удаляются соединения с БД. Я закодировал вокруг различных возможных случаев. В моем коде я проверяю, имеет ли _connection значение null, и соответственно создаю новое соединение. При выполнении запросов я обнаруживаю, что иногда соединение остается открытым, а иногда я обнаруживаю, что в объекте отсутствует строка соединения (что делает его непригодным для использования, но не устанавливает его в NULL). Я рассматриваю эти случаи соответственно, но хотел бы понять, почему соединение имеет эти изменяющиеся состояния, и не утилизируется, даже если клиентский код явно реализует оператор using для переноса кода. Это ADO.net обработка соединений, есть ли побочный эффект Dapper или просто проблемы с моим кодом?

Код управления подключением

public class DatabaseContext : IDatabaseContext 
{
    private readonly string _connectionString;

    private DbConnection _connection;


    public DatabaseContext(string connectionString)
    {
        _connectionString = connectionString;

    }

    public IDbConnection Connection
    {
        get
        {

            if (_connection == null)
                _connection = new SqlConnection(_connectionString);

            if (string.IsNullOrEmpty(_connection.ConnectionString))
                _connection.ConnectionString = _connectionString;

            if (_connection.State != ConnectionState.Open)
                _connection.Open();

            return _connection;
        }
    }
}

Код клиента

public IEnumerable<PostSearResults> Search(SearchPostsBy searchPostsBy)
{
    DynamicParameters param;
    var sql = GetSearchSql(searchPostsBy,out param);//Gets SQL 

    using (var connection = _databaseContext.Connection)
    {
        var posts = connection.Query<PostSearResults>(sql, param);
        return posts.ToList();
    }
}

1 ответ

Я также использую Dapper в веб-приложении и реализую DapperContext, похожий на ваш, но я реализую IDispose для класса следующим образом:

    #region IDisposable

    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                if (transaction != null)
                { transaction.Dispose(); }
                if (cn != null)
                { cn.Dispose(); }
            }
        }
        this.disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    #endregion

Моя версия Dapper - это та, которая открывает соединение, если оно закрывается, когда мы выполняем вызов, затем закрывается после выполнения запроса, если соединение открывается, когда я выполняю вызов, Dapper просто выполняет запрос и оставляет соединение открытым.

Я также использую DI, поэтому мое время жизни DapperContext управляется контейнером DI, поэтому он удаляется после завершения и уничтожения контекста веб-запроса. Мой Dapper Repository выглядит следующим образом, с примером метода GetPE

private readonly IDbConnection context;
private readonly DapperContext dapperContext;

public SFRepository(DapperContext dbContext)
{
    dapperContext = dbContext;
    context = dbContext.Connection;
}

public PEData GetPE(int peID)
{
     PEData rec = context.Query<PEData>("SELECT * FROM PEDATA WHERE ID= @ID", new { ID = peID }).FirstOrDefault();

     return rec;
}

Это было очень стабильно, и у меня нет странного поведения.

Другие вопросы по тегам