web-dev-qa-db-fra.com

Pagination des énormes données renvoyées par l'API Web

Nous avons créé WebAPI pour interroger une base de données Oracle. La requête renvoie des résultats énormes, donc elle lance parfois OutOfMemoryException.

La recommandation était d'utiliser le concept Paging. Je ne comprends pas comment l'application cliente saura combien de fois l'API doit être appelée pour obtenir l'ensemble complet du résultat. Dois-je également créer une classe distincte pour la pagination ou puis-je l'exploiter dans mon contrôleur API.

Quelqu'un peut-il m'aider s'il vous plaît, car c'est ma première API Web. Nous ne pouvons pas créer de procédures stockées pour cela car nous avons juste un accès en lecture sur la base de données

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

L'idée générale derrière la pagination via l'API est que le client passera la "page" de données qu'il souhaite et la "quantité" d'enregistrements qu'il souhaite.

De là, vous pouvez structurer votre requête quelque chose à l'effet de

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

Si vous utilisez LINQ to SQL, il existe des méthodes Take () et Skip () qui facilitent grandement l'écriture côté code. Si vous n'utilisez pas LINQ to SQL, vous devrez trouver quelque chose de spécifique à Oracle.

Remarque finale, étant donné qu'une bonne API est conçue pour être "sans état", le client devra maintenir la page sur laquelle il se trouve lors du traitement des requêtes de page précédente/suivante. En règle générale, les variables de page et de montant sont conservées en Javascript ou même quelque chose d'aussi simple que des variables cachées et peuvent être utilisées pour calculer le nombre de pages disponibles, etc.

Voici un exemple de base d'un appel WebAPI que je fais qui fait de la pagination. Vous devrez peut-être le modifier un peu pour prendre en charge l'obtention de tous les enregistrements et potentiellement tout ce qui est spécifique à Oracle si LINQ to SQL/EF ne le prend pas en charge:

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