Dapper одноразовый экземпляр с Ninject - PullRequest
0 голосов
/ 08 июня 2018

Я хочу связать экземпляр подключения к базе данных, используя Ninject, и использовать его в рамках потока, чтобы пропустить многократный ввод using { var cn = new DbConnectionFactory() } [..] всякий раз, когда мне нужно сделать запрос.

Я добавил привязку:

IOC.Kernel.Bind<IDbConnection>().ToMethod(ctx =>
{
    using (var cn = new DbConnectionFactory())
    {
        return cn.GetConnection();
    }
}).InThreadScope();

db фабричный класс:

public class DbConnectionFactory : IDisposable
{
    private IDbConnection _connection;

    public DbConnectionFactory()
    {
        _connection = new SQLiteConnection("Data Source=mydb.sqlite;Version=3;");
        _connection.Open();
    }

    public IDbConnection GetConnection() => _connection;

    public void Dispose()
    {
        _connection.Close();
    }
}

Теперь все работает нормально.Для каждого потока создается одно дБ-соединение, однако соединение закрывается, но не удаляется!

Поэтому, когда я изменяю свой метод Dispose для этого:

public void Dispose()
{
    _connection.Close();
    _connection.Dispose();
}

Соединение неткажется, работает дольше, и при доступе выдает исключение: ObjectDisposedException Объект больше не доступен.

Вопрос: как правильно связать и утилизировать соединение в Ninject?

Пожалуйстаобратите внимание, что я не могу использовать .InRequestScope (), потому что это не веб-приложение.

1 Ответ

0 голосов
/ 08 июня 2018

Для контейнеров Ninject и других контейнеров IoC контейнер отвечает за вызов Dispose для одноразовых предметов.К сожалению, в вашей реализации вы сами вызываете Dispose - и делаете это неправильно.

using (var cn = new DbConnectionFactory())
{
    return cn.GetConnection();
}

Этот код создает DbConnectionFactory и создает соединение с базой данных.Затем (из-за using) он вызывает cn.Dispose.Тогда ваша реализация избавится от нового соединения, которое вы только что создали.

Существует несколько способов решения этой проблемы, но я бы предложил начать с изменения:

public class DbConnectionFactory
{
    public IDbConnection GetConnection() 
    {
        var connection = new SQLiteConnection("Data Source=mydb.sqlite;Version=3;");
        connection.Open();
        return connection;
    }
}

А затем:

IOC.Kernel.Bind<IDbConnection>().ToMethod(ctx =>
{
    var cn = new DbConnectionFactory();
    return cn.GetConnection();
}).InThreadScope();

Затем, согласно документам , соединение с базой данных будет автоматически Dispose d, когда базовый Thread будет собирать мусор.

...