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