2

私のWebアプリケーションには次のクラスがあります。

public class DatabaseProvider {
    private readonly IDbConnection _cn;

    public DatabaseProvider(IDbConnection cn) {
        _cn = cn;
    }

    public void ExecuteNonQuery(string query) {
        // Execute the query
        var cmd = _cn.CreateCommand();
        cmd.CommandText = query;
        cmd.ExecuteNonQuery();
    }
}

IDbConnectionの依存関係が次のコードを使用して宣言されている場合(Microsoft Unityを使用):

container.RegisterType<IDbConnection>(new InjectionFactory(c => {
    var cn = new SqlConnection("...");
    cn.Open();
    return cn;
}));

これにより、SQLiteへの接続を次のように交換できます。

container.RegisterType<IDbConnection>(new InjectionFactory(c => {
    var cn = new SQLiteConnection("Data Source=:memory:;Version=3;");
    cn.Open();
    return cn;
}));

テスト時にSQLiteを使用しますが、接続を開いたままにしておく必要があります。そうしないと、データが失われます。したがって、必要なときに接続を開いたり閉じたりすることはできません。

私は常にデータベースへの接続を必要なときに開いていましたが、これが大規模なアプリケーションに対応できるかどうか疑問に思っていましたか?

これをどのように改善できるかについてアドバイスをいただければ幸いです。ありがとう

4

3 に答える 3

5

ADO.NETの原則として、接続はできるだけ早く閉じる必要があります。

接続は接続プールから再利用され、リソースが不足しています。

これを行うための推奨される方法は、(){}構文を使用することです。

SQL Server接続プール(ADO.NET)

接続がプールに戻されるように、使用が終了したら常に接続を閉じることを強くお勧めします。これを行うには、ConnectionオブジェクトのCloseメソッドまたはDisposeメソッドを使用するか、C#のusingステートメントまたはVisualBasicのUsingステートメント内のすべての接続を開きます。明示的に閉じられていない接続は、プールに追加または戻されない場合があります。詳細については、「ステートメントの使用(C#リファレンス)」または「方法:Visual Basicのシステムリソースの破棄(Visual Basic)」を参照してください。

したがって、インターフェイスIDbProviderを作成してから、 SqlServerProviderSQLiteProviderの2つの実装を作成し、それらの内部で接続の開始と終了を処理することをお勧めします。次に、Unityを使用して1つのプロバイダーまたは別のプロバイダーをバインドします。

于 2012-10-10T12:51:28.583 に答える
0

Unityで接続をインスタンス化するときは、開かないでください。ただし、通常どおりコードで最初に使用するときに開き、不要になったときに閉じます。

これにより、DatabaseProviderが変更されます

public class DatabaseProvider {
    private readonly IDbConnection _cn;

    public DatabaseProvider(IDbConnection cn) {
        _cn = cn;
    }

    public void ExecuteNonQuery(string query) {
        // Execute the query
        try{
           _cn.Open();
           var cmd = _cn.CreateCommand();
           cmd.CommandText = query;
           cmd.ExecuteNonQuery();
        }
        catch(ExpectedExceptions){
           //take care of business
        }
        finally{
            _cn.Close();
        }

    }
}

Unityがインスタンスの作成に使用するスコープとスパンされたライフタイムに注意してください。上記のソリューションはスレッドセーフではありません。異なるスレッドに同じインスタンスがあると、優れたデバッグフェストが発生する可能性があります。

于 2012-10-10T13:00:59.090 に答える
0

こちらもチェックできます。

そして、私のやり方では、常に接続状態をチェックし、開いたら閉じます。

public class DatabaseProvider {
    private readonly IDbConnection _cn;

    public DatabaseProvider(IDbConnection cn) {
        _cn = cn;
    }

    public void ExecuteNonQuery(string query) {

        using(SqliteCommand cmd = new SqliteCommand{ Connection = _cn})
        {

            if(_cn.State == ConnectionState.Open)
               _cn.Close();

            try
            {
               _cn.Open();
            }
            catch
            {
               // Message Connection Error
            }

            try
            {
               cmd.CommandText = query;
               cmd.ExecuteNonQuery();
            }
            catch
            {
                // Message Query Error
            }
            finally
            {
                _cn.Close();  // Connection close
            }

        }


    }
}
于 2017-09-17T03:03:58.527 に答える