大量の結果から各レコードの関数を呼び出す

asp.net-mvc-5 c# dapper

質問

フィールド値を設定する各レコードで関数を呼び出そうとしています。結果がページングされることを意味するとき、これは次の方法で達成されます。

public IDataWrapper GetPagedQuery<T>(string myQuery, object param, Action<T> customAction)
{
    var obj = new DataWrapper ();
    using (var oConn = CreateConnection(ConnectionString))
    {
        TotalPages totalRows = null;
        var list = oConn.Query<T, TotalPages, T>(myQuery, (e, t) =>
        {
            totalRows = t;
            if (mapAction != null) customAction(e);
            return e;
        }, param, splitOn: "SplitOn");
        obj.RowsFound = (IEnumerable<dynamic>)list;
        obj.TotalRows = totalRows == null ? 0 : totalRows.TotalRows;
    }
    return obj;
}

私の問題は、結果がページングされることを意図していないときに来る。最初の例の私のクエリにはsplit on columnが含まれているので、これはすべて動作しますが、次のクエリはSelect Column1, Column2 FROM MyAwesomeTableなどの単純なクエリです。

問題は、戻ってくる各結果に対してcustomActionを適用する必要があることです。今度は数百万のレコードが潜在する可能性があることを想像してみてください。私の状況では、これは非現実的ではないと私に信じてください。最初のケースと同じように、ダッパーが結果を返すときに適用されます。

ここで私が試したものです:

public IDataWrapper GetNonPagedQuery<T>(string myQuery, object param, Action<T> customAction)
{
    var obj = new DataWrapper ();
    using (var oConn = CreateConnection(ConnectionString))
    {
        var list = oConn.Query<T>(myQuery, (e) =>
        {
            if (mapAction != null) customAction(e);
            return e;
        }, param).ToList();
        obj.RowsFound = (IEnumerable<dynamic>)list;
        obj.TotalRows = list.Count();
    }
    return obj;
}

上記のコードでは、メソッドQuery<T>(etc...解決できないというエラーが出ますQuery<T>(etc... 、それが存在しないためです)。私はここで何をしようとしているのかを尋ねる?それは大胆で可能ですか?

受け入れられた回答

私は、短い答えはあなたがこれをすることができないことであると思います。

もう少し長い答えは、あなたのページングされたクエリで 、Dapperが各行のデータを "T"のインスタンスに変換する作業をしてから、 "map"メソッドあなたはあなたの "customAction"を呼び出すために使用します。

したがって、単純な非ページング "conn.Query"コールに続いてcustomActionを実行するための後続のパスを実行することと、それとほとんど違いはありません。次のようなもの:

public IDataWrapper GetNonPagedQuery<T>(string myQuery, object param, Action<T> customAction)
{
    var obj = new DataWrapper();
    using (var oConn = CreateConnection(ConnectionString))
    {
        var results = oConn
            .Query<T>(myQuery)
            .ToList();
        obj.TotalRows = results.Count();
        obj.RowsFound = results
            .Select(value =>
            {
                customAction(value);
                return value;
            })
            .Cast<dynamic>();
    }
    return obj;
}

非ページングされたクエリの多くのレコードを読み込んでいる可能性がある場合は、それらのレコードがすべて一度にメモリにロードされることに気をつけてください。返された結果を列挙するときに1つずつデータベースから取り出されることはありません。また、リソースがかなり消費される可能性があります(2回目の列挙を避けるために非常に多くのデータを扱っている場合) 。

これは、GetNonPagedQueryが返ってくるのでSQL接続が閉じられているため、呼び出し元がデータを「オンデマンド」で読むことができないままになることはありません。大量のデータを実際に処理している場合は、ページングされていないクエリが最適なアプローチではないかもしれません。

上記のコードでは、 "customAction"は、行を列挙するときにのみ呼び出され、GetNonPagedQueryが返される前にすべて呼び出されるわけではありません。 「customAction」が高価な操作である可能性がある場合は、このメリットがあります。一方、GetNonPagedQueryが返される前にすべての結果に対して "customAction"を呼びたい場合は、Cast <dynamic>()の後にもう1つのToList()コールが必要になります。


人気のある回答

はい、可能です:

行ごとのタイプ切り替えについては、Dapperのドキュメントのセクションを参照してください。私は、同じシステムを使用して、各行を読み込んで明示的に処理して結果を目的のフォーマットにマッサージすると、うまくいかないと思っています(つまり自分で試してみません)。



ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow