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());
        }
Esempio n. 2
0
        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);
        }