第二次执行

时间:2017-10-25 18:04:39

标签: c# dependency-injection asp.net-core asp.net-core-mvc

我正在使用asp.net core 2.0和dapper。我有一个包装IDbConnection接口的类,只暴露某些方法。这是该课程的简短版本。

public class MyConnectionString : IMyConnectionString
{
    private readonly IDbConnection _connection;

    public int ConnectionTimeout => _connection.ConnectionTimeout;
    public string Database => _connection.Database;
    public string ConnectionString { get => null; set => _connection.ConnectionString = value; }
    public ConnectionState State => _connection.State;

    public MyConnectionString(IOptions<ConnectionProviderOptions> connProvOpts, EncryptionHelper encHelper)
    {
        var con = "some logic to get the connection string.";
        _connection = new SqlConnection(con);
    }

    public int Execute(string query, object parameters = null)
    {
        using (var con = _connection) { return con.Execute(query, parameters); }
    }
}

我通过构造函数将此类注入到我的Repository服务中。例如,这是一个可以调用它的方法:

internal class SomeRepository
{
    private readonly IMyConnectionString _connection;

    public SomeRepository(IMyConnectionString connection)
    {
        _connection = connection;
    }

    public void ExecuteSomeQuery(Object params)
    {
        var query = "Some query...";
        _connection.Execute(query, params);
    }
}

现在的问题是,如果我在单个请求中调用_connection.Execute(query, params);两次(2个不同的服务),则第二次调用ConnectionString类中的MyConnectionString值为空。我试过在Transient和Request范围内绑定它,看它是否会保留它,但没有运气。任何关于为什么会发生这种情况的想法或者如何保留它以便我不必在每次请求时都创建连接字符串?

1 个答案:

答案 0 :(得分:2)

Connection包裹在using内,将Connection置于执行结束处:正如@Jasen在评论中所述。

在您的情况下,我会在构造函数中创建的Connection上获取连接并执行:完全删除using

您不应创建SqlConnection,因为您正在实现依赖注入。你应该:

  • 实施IDisposable以在收集课程时处理您的连接。
  • 通过SqlConnection工厂创建SqlConnection,从班级中分离您的创作逻辑。

你的课应该像这样:

public class MyConnectionString : IMyConnectionString
{
    private readonly IDbConnection _connection;

    public int ConnectionTimeout => _connection.ConnectionTimeout;
    public string Database => _connection.Database;
    public string ConnectionString 
    {     
        get => null; 
        set => _connection.ConnectionString = value; 
    }

    public ConnectionState State => _connection.State;

    public MyConnectionString(IOptions<ConnectionProviderOptions> connProvOpts, EncryptionHelper encHelper)
    {
        string con = "some logic to get the connection string.";
        _connection = new SqlConnection(con);
    }

    public int Execute(string query, object parameters = null)
    {
        return _connection.Execute(query, parameters);
    }
}

IDisposable实施:

using System;
public class MyConnectionString : IMyConnectionString, IDisposable
{
    private readonly IDbConnection _connection;

    public int ConnectionTimeout => _connection.ConnectionTimeout;
    public string Database => _connection.Database;
    public string ConnectionString 
    {     
        get => null; 
        set => _connection.ConnectionString = value; 
    }

    public ConnectionState State => _connection.State;

    public MyConnectionString(IOptions<ConnectionProviderOptions> connProvOpts, EncryptionHelper encHelper)
    {
        string con = "some logic to get the connection string.";
        _connection = new SqlConnection(con);
    }

    public int Execute(string query, object parameters = null)
    {
        return _connection.Execute(query, parameters);
    }

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

使用您自己的ISqlConnectionFactory工厂:

public class MyConnectionString : IMyConnectionString, IDisposable
{
    private readonly IDbConnection _connection;
    private readonly ISqlConnectionFactory _factory;

    public int ConnectionTimeout => _connection.ConnectionTimeout;
    public string Database => _connection.Database;
    public string ConnectionString 
    {     
        get => null; 
        set => _connection.ConnectionString = value; 
    }

    public ConnectionState State => _connection.State;

    public MyConnectionString(IOptions<ConnectionProviderOptions> connProvOpts, EncryptionHelper encHelper, ISqlConnectionFactory factory)
    {
        _factory = factory;
        _connection = _factory.CreateConnection(connProvOpts, encHelper);
    }

    public int Execute(string query, object parameters = null)
    {
        return _connection.Execute(query, parameters);
    }
}

public interface ISqlConnectionFactory
{
    SqlConnection CreateConnection(IOptions<ConnectionProviderOptions> connProvOpts, EncryptionHelper encHelper);
}

public class SqlConnectionFactory : ISqlConnectionFactory
{
    public SqlConnectionFactory()
    {
         // Maybe initialization?
    }

    public SqlConnection CreateConnection(IOptions<ConnectionProviderOptions> connProvOpts, EncryptionHelper encHelper)
    {
        string con = "some logic to get the connection string.";
        _connection = new SqlConnection(con);
    }
}

就个人而言,每次调用Connection时,我都会创建并处理Execute。这意味着在Execute之外,您的连接将关闭,资源将被释放。