public async Task <FeedPackageDetails> GetPackageOrNull(string id, string version) { if (id == null) { throw new ArgumentNullException(nameof(id)); } if (version == null) { throw new ArgumentNullException(nameof(version)); } var packages = new List <FeedPackageDetails>(); var packageQuery = BuildGetPackageSqlQuery(); using (var sqlConnection = await _connectionFactory.OpenAsync()) { using (var packagesCommand = new SqlCommand(packageQuery, sqlConnection) { CommandTimeout = _commandTimeout }) { packagesCommand.Parameters.AddWithValue(PackageIdParameterName, id); packagesCommand.Parameters.AddWithValue(PackageVersionParameterName, version); using (_telemetryService.TrackGetPackageQueryDuration(id, version)) { using (var packagesReader = await packagesCommand.ExecuteReaderAsync()) { while (await packagesReader.ReadAsync()) { packages.Add(_db2catalogProjection.ReadFeedPackageDetailsFromDataReader(packagesReader)); } } } } } return(packages.SingleOrDefault()); }
private async Task <IReadOnlyCollection <FeedPackageDetails> > ReadPackagesAsync(SqlCommand packagesCommand) { var packages = new List <FeedPackageDetails>(); using (var packagesReader = await packagesCommand.ExecuteReaderAsync()) { // query has been ordered by package/version key, so we can use control break logic here to read it efficiently // - we break on key change to find the end of a group of rows for which we must accumulate vulnerability data if (await packagesReader.ReadAsync()) // priming read { var key = _db2catalogProjection.ReadPackageVersionKeyFromDataReader(packagesReader); var readEnded = false; do { var package = _db2catalogProjection.ReadFeedPackageDetailsFromDataReader(packagesReader); packages.Add(package); // loop through all rows with the same key, so we cover all vulnerabilities for package/version var thisKey = key; do { var vulnerability = _db2catalogProjection.ReadPackageVulnerabilityFromDataReader(packagesReader); if (vulnerability != null) { package.AddVulnerability(vulnerability); } // read next, prime for control break if (await packagesReader.ReadAsync()) { key = _db2catalogProjection.ReadPackageVersionKeyFromDataReader(packagesReader); } else { readEnded = true; } } while (!readEnded && key == thisKey); } while (!readEnded); } } return(packages); }