web-dev-qa-db-ja.com

Web APIによって返される巨大なデータのページング

Oracleデータベースを照会するためのWebAPIを作成しました。クエリは膨大な結果を返すため、OutOfMemoryExceptionがスローされることがあります。

Pagingコンセプトを使用することをお勧めしました。結果のセット全体を取得するためにクライアントアプリケーションがAPIを何回呼び出す必要があるかを知る方法がわかりません。また、ページング用に別のクラスを作成する必要がありますか、それともAPIコントローラーで操作できますか?.

これは私の最初のWeb APIなので、誰かがこれを手伝ってくれませんか?データベースに対する読み取りアクセス権しかないため、このためのストアドプロシージャを作成できません。

public HttpResponseMessage Getdetails([FromUri] string[] id)
{
    string connStr = ConfigurationManager.ConnectionStrings["ProDataConnection"].ConnectionString;
    using (OracleConnection dbconn = new OracleConnection(connStr))
    {
         var inconditions = id.Distinct().ToArray();
         var srtcon = string.Join(",", inconditions);
         DataSet userDataset = new DataSet();
         var strQuery = @"SELECT * from STCD_PRIO_CATEGORY where STPR_STUDY.STD_REF IN(" + srtcon + ")";
         using (OracleCommand selectCommand = new OracleCommand(strQuery, dbconn))
         {
              using (OracleDataAdapter adapter = new OracleDataAdapter(selectCommand))
             {
                 DataTable selectResults = new DataTable();
                 adapter.Fill(selectResults);
                 var returnObject = new { data = selectResults };
                 var response = Request.CreateResponse(HttpStatusCode.OK, returnObject, MediaTypeHeaderValue.Parse("application/json"));
                 ContentDispositionHeaderValue contentDisposition = null;

                 if (ContentDispositionHeaderValue.TryParse("inline; filename=ProvantisStudyData.json", out contentDisposition))
                {
                     response.Content.Headers.ContentDisposition = contentDisposition;
                }

                return response;
            }
        }
    }
}
12
user4912134

APIによるページングの背後にある一般的な考え方は、クライアントが必要なデータの「ページ」と必要なレコードの「量」を渡すことです。

そこからクエリを構造化して、

Select all records, but skip ((Page - 1) * amount) of records and take (amount) of records.

LINQ to SQLを使用する場合、Take()およびSkip()メソッドがあり、コード側でこれを非常に簡単に記述できます。 LINQ to SQLを使用していない場合は、Oracle固有のものを見つける必要があります。

最後に、優れたAPIは「ステートレス」であるように設計されているため、クライアントは前/次のページクエリを処理するときに、どのページにいるかを維持する必要があります。通常、ページ変数と金額変数はJavascriptまたは非表示変数と同じくらい単純なもので保持され、使用可能なページ数の計算などに使用できます。

これは、ページングを実行するWebAPI呼び出しの基本的なサンプルです。 LINQ to SQL/EFでサポートされていない場合は、すべてのレコードを取得し、Oracle固有の情報を取得できるように、少し変更する必要があります。

public IActionResult GetProducts(int? page, int? count)
        {
            var takePage = page ?? 1;
            var takeCount = count ?? DefaultPageRecordCount;

            var calls = context.Products
                            .Skip((takePage - 1) * takeCount)
                            .Take(takeCount)
                            .ToList();

            return Json(calls);
        }
12
Dillie-O
IQueryable<ShowMedicineViewModel> query;
List<ShowMedicineViewModel> medic = new List<ShowMedicineViewModel>();
var medicineInfo = _dbContext.medicine_details.Where(m => (m.Medicine_name.StartsWith(medicinename)) && (m.Medicine_type == medicinetype)).ToList();   

List<string> TotalMedicine = new List<string>();

var results = (medicineInfo.OrderBy(x => x.id)
              .Skip((pages - 1) * 2)
              .Take(2));


Parallel.ForEach(results, item =>
{
    var temp = Mapper.DynamicMap<medicine_details, ShowMedicineViewModel>(item);

    medic.Add(temp);
});

Dictionary<string, int> dictionary2 = new Dictionary<string, int>();
dictionary2.Add("CurrentPage", pages);
dictionary2.Add("TotalPages", medicineInfo.Count() / 2 < 1 ? 1 : medicineInfo.Count());

Dictionary<string, object> dictionary = new Dictionary<string, object>();
dictionary.Add("Data", medic);
dictionary.Add("Page", dictionary2);

return dictionary;
0
Debendra Dash