2017-10-25 21 views
0

私はasp.net core 2.0とdapperを使用しています。 IDbConnectionインターフェイスをラップし、特定のメソッドのみを公開するクラスがあります。ここにそのクラスの短いバージョンがあります。2番目の実行時にConnectionStringが失われる

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); } 
    } 
} 

私はこのクラスをコンストラクタを介してリポジトリサービスに注入しています。たとえば、これはそれを呼ぶだろう方法である:

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); 
    } 
} 

今の問題は、私は単一の要求(2つの異なるサービス)で二回_connection.Execute(query, params);を呼び出す場合、それを取得二度目はMyConnectionStringConnectionString値と呼ばれるということですクラスは空です。私はTransientとRequestスコープでバインドして、それを保存するかどうかを確認しましたが、運はありません。なぜこのようなことが起こっているのか、どのように私はそれを保存して、要求されるたびに接続文字列を作成する必要がないのでしょうか?

+2

"MyConnectionStringクラス内のConnectionString値が空です" ... "ConnectionString {get => nullを返します。 ... '、あなたはそれが'ヌル '以外のものを返すとどう思いますか? –

+4

また 'using(var con = _connection)'は、最初の実行後に '_connection'を効果的に破棄します。 – Jasen

+1

代わりに、すべての要求に対して新しい接続を作成する必要があります。接続プーリングに起因するオーバーヘッドはほとんどありません。また、特定のDappersメソッドのみを公開するためにファサードを使用する目的は何ですか?私はこれで何の利益も見ません。 –

答えて

2

Connectionusingの中にラップすると、実行終了時にConnectionが処理されます。@ジャセンはコメントのように述べています。

あなたの場合は、コンストラクタで作成されたConnectionで接続を取得して実行します。usingを完全に削除します。

依存性注入を実装しているので、SqlConnectionは作成しないでください。あなたは:

  • IDisposableを実装して、クラスを収集するときに接続を破棄する必要があります。
  • 工場にSqlConnectionを渡してSqlConnectionを作成し、クラスから作成ロジックを分離します。

このような何かに似ている必要がありますあなたのクラス:自分のISqlConnectionFactory工場で

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(); 
    } 
} 

IDisposable実装で

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); 
    } 
} 

を個人的に

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); 
    } 
} 

、私が持っているでしょう作成したExecuteが呼び出されるたびにConnectionが配置されます。つまり、Executeの外部に接続が閉じられ、リソースが解放されます。

+1

これを行うと、 'SqlConnection'を注入するか、' IDisposable'を実装する必要があります。 – Jasen

+0

本当に、私は彼の接続文字列がどこから来たのだろうと思っていました。確かに彼のコンストラクタのパラメータから。 –

+0

ありがとうございます。私は新しい変数を作成しているので、オブジェクトは複製され、新しいオブジェクトは元のオブジェクトではなく廃棄されると私は考えました。 – Bojan

関連する問題