mirror of
https://github.com/Sonarr/Sonarr
synced 2025-02-20 13:17:17 +00:00
Added populate lazy-loading extensions.
This commit is contained in:
parent
88cd6a3213
commit
b133fa9585
5 changed files with 75 additions and 33 deletions
|
@ -1,17 +1,22 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Api.REST;
|
using NzbDrone.Api.REST;
|
||||||
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Api.Extensions;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Episodes
|
namespace NzbDrone.Api.Episodes
|
||||||
{
|
{
|
||||||
public class EpisodeModule : NzbDroneRestModule<EpisodeResource>
|
public class EpisodeModule : NzbDroneRestModule<EpisodeResource>
|
||||||
{
|
{
|
||||||
private readonly IEpisodeService _episodeService;
|
private readonly IEpisodeService _episodeService;
|
||||||
|
private readonly MediaFileRepository _mediaFileRepository;
|
||||||
|
|
||||||
public EpisodeModule(IEpisodeService episodeService)
|
public EpisodeModule(IEpisodeService episodeService, MediaFileRepository mediaFileRepository)
|
||||||
: base("/episodes")
|
: base("/episodes")
|
||||||
{
|
{
|
||||||
_episodeService = episodeService;
|
_episodeService = episodeService;
|
||||||
|
_mediaFileRepository = mediaFileRepository;
|
||||||
|
|
||||||
GetResourceAll = GetEpisodes;
|
GetResourceAll = GetEpisodes;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +30,10 @@ namespace NzbDrone.Api.Episodes
|
||||||
throw new BadRequestException("seriesId is missing");
|
throw new BadRequestException("seriesId is missing");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ToListResource(() => _episodeService.GetEpisodeBySeries(seriesId.Value));
|
var resource = ToListResource(() => _episodeService.GetEpisodeBySeries(seriesId.Value))
|
||||||
|
.LoadSubtype(e => e.EpisodeFileId, _mediaFileRepository);
|
||||||
|
|
||||||
|
return resource.ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
53
NzbDrone.Api/Extensions/LazyExtensions.cs
Normal file
53
NzbDrone.Api/Extensions/LazyExtensions.cs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using NzbDrone.Api.REST;
|
||||||
|
using NzbDrone.Common.Cache;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Extensions
|
||||||
|
{
|
||||||
|
public static class LazyExtensions
|
||||||
|
{
|
||||||
|
private static readonly ICached<MethodInfo> SetterCache = new Cached<MethodInfo>();
|
||||||
|
|
||||||
|
public static IEnumerable<TParent> LoadSubtype<TParent, TChild>(this IEnumerable<TParent> parents, Func<TParent, int> foreignKeySelector, IBasicRepository<TChild> childRepository)
|
||||||
|
where TChild : ModelBase, new()
|
||||||
|
where TParent : RestResource
|
||||||
|
{
|
||||||
|
var parentList = parents.Where(p => foreignKeySelector(p) != 0).ToList();
|
||||||
|
|
||||||
|
if (!parentList.Any())
|
||||||
|
{
|
||||||
|
return parents;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ids = parentList.Select(foreignKeySelector).Distinct();
|
||||||
|
var childDictionary = childRepository.Get(ids).ToDictionary(child => child.Id, child => child);
|
||||||
|
|
||||||
|
var childSetter = GetChildSetter<TParent, TChild>();
|
||||||
|
|
||||||
|
foreach (var episode in parentList)
|
||||||
|
{
|
||||||
|
childSetter.Invoke(episode, new object[] { childDictionary[foreignKeySelector(episode)] });
|
||||||
|
}
|
||||||
|
|
||||||
|
return parents;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static MethodInfo GetChildSetter<TParent, TChild>()
|
||||||
|
where TChild : ModelBase
|
||||||
|
where TParent : RestResource
|
||||||
|
{
|
||||||
|
var key = typeof(TChild).FullName + typeof(TParent).FullName;
|
||||||
|
|
||||||
|
return SetterCache.Get(key, () =>
|
||||||
|
{
|
||||||
|
var property = typeof(TParent).GetProperties().Single(c => c.PropertyType == typeof(TChild));
|
||||||
|
return property.GetSetMethod();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -86,6 +86,9 @@
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="..\NzbDrone.Common\Properties\SharedAssemblyInfo.cs">
|
||||||
|
<Link>Properties\SharedAssemblyInfo.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Authentication\AuthenticationService.cs" />
|
<Compile Include="Authentication\AuthenticationService.cs" />
|
||||||
<Compile Include="Authentication\EnableBasicAuthInNancy.cs" />
|
<Compile Include="Authentication\EnableBasicAuthInNancy.cs" />
|
||||||
<Compile Include="Authentication\NzbDroneUser.cs" />
|
<Compile Include="Authentication\NzbDroneUser.cs" />
|
||||||
|
@ -111,6 +114,7 @@
|
||||||
<Compile Include="Indexers\IndexerModule.cs" />
|
<Compile Include="Indexers\IndexerModule.cs" />
|
||||||
<Compile Include="Indexers\IndexerResource.cs" />
|
<Compile Include="Indexers\IndexerResource.cs" />
|
||||||
<Compile Include="Indexers\ReleaseModule.cs" />
|
<Compile Include="Indexers\ReleaseModule.cs" />
|
||||||
|
<Compile Include="Extensions\LazyExtensions.cs" />
|
||||||
<Compile Include="Mapping\CloneInjection.cs" />
|
<Compile Include="Mapping\CloneInjection.cs" />
|
||||||
<Compile Include="Mapping\MappingValidation.cs" />
|
<Compile Include="Mapping\MappingValidation.cs" />
|
||||||
<Compile Include="Mapping\ResourceMappingException.cs" />
|
<Compile Include="Mapping\ResourceMappingException.cs" />
|
||||||
|
|
|
@ -2,36 +2,10 @@
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
|
||||||
// set of attributes. Change these attribute values to modify the information
|
|
||||||
// associated with an assembly.
|
|
||||||
[assembly: AssemblyTitle("NzbDrone.Api")]
|
[assembly: AssemblyTitle("NzbDrone.Api")]
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyConfiguration("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("NzbDrone.Api")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © 2012")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
|
|
||||||
// Setting ComVisible to false makes the types in this assembly not visible
|
|
||||||
// to COM components. If you need to access a type in this assembly from
|
|
||||||
// COM, set the ComVisible attribute to true on that type.
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
|
||||||
[assembly: Guid("4c0922d7-979e-4ff7-b44b-b8ac2100eeb5")]
|
[assembly: Guid("4c0922d7-979e-4ff7-b44b-b8ac2100eeb5")]
|
||||||
|
|
||||||
// Version information for an assembly consists of the following four values:
|
|
||||||
//
|
|
||||||
// Major Version
|
|
||||||
// Minor Version
|
|
||||||
// Build Number
|
|
||||||
// Revision
|
|
||||||
//
|
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
|
||||||
// by using the '*' as shown below:
|
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
|
||||||
[assembly: AssemblyVersion("1.0.0.0")]
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ using Marr.Data;
|
||||||
using Marr.Data.QGen;
|
using Marr.Data.QGen;
|
||||||
using NzbDrone.Common.Messaging;
|
using NzbDrone.Common.Messaging;
|
||||||
using NzbDrone.Core.Datastore.Events;
|
using NzbDrone.Core.Datastore.Events;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Datastore
|
namespace NzbDrone.Core.Datastore
|
||||||
|
@ -79,12 +80,14 @@ namespace NzbDrone.Core.Datastore
|
||||||
|
|
||||||
public IEnumerable<TModel> Get(IEnumerable<int> ids)
|
public IEnumerable<TModel> Get(IEnumerable<int> ids)
|
||||||
{
|
{
|
||||||
var idList = ids.ToList();
|
var query = String.Format("Id IN ({0})", String.Join(",", ids));
|
||||||
var result = Query.Where(String.Format("Id IN ({0})", String.Join(",", idList))).ToList();
|
|
||||||
var resultCount = result.Count;
|
|
||||||
|
|
||||||
if (resultCount != idList.Count || result.Select(r => r.Id).Distinct().Count() != resultCount)
|
var result = Query.Where(query).ToList();
|
||||||
throw new InvalidOperationException("Unexpected result from query");
|
|
||||||
|
if (result.Count != ids.Count())
|
||||||
|
{
|
||||||
|
throw new ApplicationException("Expected query to return {0} rows but returned {1}".Inject(ids.Count(), result.Count));
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue