Getting only the latest versions with GetPackages()

Jun 16, 2011 at 7:57 AM

Hi gang,

I notice that a raw call to GetPackages() on a repository brings back every package in the source, even if there are multiple versions of the same package.

I can roll the list of packages up into a list of the latest version of each package in a number of ways:

// simple grouping
packages.GroupBy(p => p.Id).Select(g => g.OrderBy(p => p.Version).Last());

// in-build DistinctLast call
packages.DistinctLast(PackageEqualityComparer.Id, PackageComparer.Version);

In my application I'm doing some rudimentary paging on the list of packages using the Skip() and Take() extension methods, so neither of these attempts seem to work for me.

The first throws an obscure Linq error, probably because I'm trying to do some fancy grouping against an OData feed and the protocol doesn't support it. I can reproduce it if anyone would like to see the actual message.

The second works, but since it happens client side (it's an IEnumerable<T> extension rather than IQueryable<T>) then if a page of results doesn't include all versions of a package, I might be showing the user an out of date version.

Is there a built-in way to query a repository for just the most recent version of each package?


Jun 16, 2011 at 8:10 AM

I just replied to you on Twitter. I'll repeat here.

If you only deal with Odata repositories (as opposed to local repositories), you can do: GetPackages().Where(p => p.IsLatestVersion).

That's how Package Explorer does for the Select Package dialog when you select the "Only show the latest version" checkbox.

Jun 16, 2011 at 8:22 AM
dotnetjunky wrote:

If you only deal with Odata repositories (as opposed to local repositories), you can do: GetPackages().Where(p => p.IsLatestVersion).

Thank dnj.

I see what you mean - the IsLatestVersion property is only on DataServicePackage, so it's only useful if you're just querying an OData feed. I'm actually querying an AggregateRepository which talks to an OData feed and a local folder. Maybe I'll have to split the two apart and treat them as separate repositories after all.


Jun 16, 2011 at 8:44 AM

Take alook at what our dialog does (it supports full paging and sorting).

var query = repository.GetPackages().OrderBy(p => p.Id).AsBufferedEnumerable(PageSize * 3);

IList<IPackage> packages = query.Skip((pageNumber - 1) * PageSize)

Jun 16, 2011 at 8:54 AM

Interesting. So "BufferedEnumerable" effectively grabs more than what you ask for, in case a package with multiple versions spans pages?

Jun 28, 2011 at 10:40 PM

Are there any plans to move IsLatestVersion into the IPackage interface so that it can be queried from any kind of repository? It sounds like a no-brainer, but obviously there are always potential problems when you add things to an interface after the fact.


Jun 28, 2011 at 10:54 PM

It's tricky to do it in a LocalPackageRepository without enumerating over the file system. We've had some perf troubles with file enumeration in the past but it certainly would be nice to have it hanging off the interface.

Jun 28, 2011 at 11:04 PM

Yeah, the current solution of "DistinctLast" on Id and Version, and having to fetch more than a page each time in case the latest version is on the *next* page is pretty messy. I think the perf hit for local package repositories would be acceptable. Heck, sites using NuGet.Server must be doing that behind the scenes anyway, right? The packages are all just in a folder on the web server anyway.