10

私は最近Dapperを使い始めました。すべてが素晴らしく簡単に思えますが、私を混乱させ続けることが 1 つあります。接続管理です。

ドキュメントに従って:

Dapper は接続のライフサイクルを管理しません。取得した接続が開いていて、既存のデータリーダーが列挙されていないと想定します (MARS が有効になっていない場合)。

これに照らして、リポジトリメソッドの実装内でこれを開始しました。

using (var db = new SqliteConnection(connectionString)) {
    // call Dapper methods here
}

次に、多数のレコードを含むテーブルに出くわしたので、メソッドにIEnumerable<T>渡して返すことを考えました。フロントエンドで列挙可能なものを列挙し始めたときに、接続が閉じられて破棄されたことを示す例外が発生しました。前の using ブロックで呼び出しをラップしているためです。buffered: falseQuery<>

質問:これを解決する最善の方法は?
副次的な質問:私が接続を管理している方法は、それを行うための好ましい方法ですか?

4

2 に答える 2

13

私はこのリポジトリパターンを提供します:

public class Repository
{
    private readonly string _connectionString;

    public Repository(string connectionString)
    {
        _connectionString = connectionString;
    }

    protected T GetConnection<T>(Func<IDbConnection, T> getData)
    {
        using (var connection = new SqlConnection(_connectionString))
        {
            connection.Open();
            return getData(connection);
        }
    }

    protected TResult GetConnection<TRead, TResult>(Func<IDbConnection, TRead> getData, Func<TRead, TResult> process)
    {
        using (var connection = new SqlConnection(_connectionString))
        {
            connection.Open();
            var data = getData(connection);
            return process(data);
        }
    }
}

バッファリングされたクエリの場合、GetConnectionメソッドの最初のオーバーロードを使用する必要があります。バッファリングされていない場合は、データを処理するためのコールバックを指定する 2 番目のオーバーロードを使用します。

public class MyRepository : Repository
{
    public MyRepository(string connectionString) : base(connectionString)
    {
    }

    public IEnumerable<MyMapObject> GetData()
    {
        return GetConnection(c => c.Query<MyMapObject>(query));
    }

    public IEnumerable<ResultObject> GetLotsOfData(Func<IEnumerable<MyMapObject>, IEnumerable<ResultObject>> process)
    {
        return GetConnection(c => c.Query<MyMapObject>(query, buffered: false), process);
    }
}

非常に基本的な使い方:

static void Main(string[] args)
{
    var repository = new MyRepository(connectionString);
    var data = repository.GetLotsOfData(ProcessData);
}

public static IEnumerable<ResultObject> ProcessData(IEnumerable<MyMapObject> data)
{
    foreach (var record in data)
    {
        var result = new ResultObject();
        //do some work...
        yield return result;
    }
}

ただし、この場合、接続が長時間開かれている可能性があることに注意してください...

于 2014-04-14T14:04:12.060 に答える