SeriesProvider is now Subsonic free.

This commit is contained in:
kay.one 2011-06-15 23:33:01 -07:00
parent 63f6899894
commit cb8cb1691f
10 changed files with 195 additions and 140 deletions

View File

@ -13,6 +13,7 @@ using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework;
using PetaPoco;
using SubSonic.Repository;
using TvdbLib.Data;
@ -22,6 +23,29 @@ namespace NzbDrone.Core.Test
// ReSharper disable InconsistentNaming
public class EpisodeProviderTest : TestBase
{
[Test]
public void GetEpisodesBySeason_success()
{
var episodes = Builder<Episode>.CreateListOfSize(10)
.WhereAll().Have(c => c.SeriesId = 12)
.WhereTheFirst(5).Have(c => c.SeasonNumber = 1)
.AndTheRemaining().Have(c => c.SeasonNumber = 2).Build();
var db = MockLib.GetEmptyDatabase();
var mocker = new AutoMoqer();
mocker.SetConstant(db);
episodes.ToList().ForEach(c => db.Insert(c));
//Act
var seasonEposodes = mocker.Resolve<EpisodeProvider>().GetEpisodesBySeason(12, 2);
//Assert
db.Fetch<Episode>().Should().HaveCount(10);
seasonEposodes.Should().HaveCount(5);
}
[Test]
public void RefreshEpisodeInfo_emptyRepo()
{
@ -42,7 +66,7 @@ namespace NzbDrone.Core.Test
var mocker = new AutoMoqer();
mocker.SetConstant(MockLib.GetEmptyRepository());
mocker.SetConstant(MockLib.GetEmptyDatabase());
mocker.GetMock<TvDbProvider>()
.Setup(c => c.GetSeries(seriesId, true))
@ -61,65 +85,72 @@ namespace NzbDrone.Core.Test
[Test]
public void new_episodes_only_calls_AddMany()
public void new_episodes_only_calls_Insert()
{
const int seriesId = 71663;
var fakeEpisodes = Builder<TvdbSeries>.CreateNew()
var tvdbSeries = Builder<TvdbSeries>.CreateNew()
.With(c => c.Episodes = new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(5).Build())
).With(c => c.Id = seriesId).Build();
var fakeSeries = Builder<Series>.CreateNew().With(c => c.SeriesId = seriesId).Build();
var currentEpisodes = new List<Episode>();
var mocker = new AutoMoqer();
mocker.GetMock<TvDbProvider>(MockBehavior.Strict)
.Setup(c => c.GetSeries(seriesId, true))
.Returns(fakeEpisodes);
.Returns(tvdbSeries);
mocker.GetMock<IDatabase>()
.Setup(d => d.Fetch<Episode>(It.IsAny<String>(), It.IsAny<Object[]>()))
.Returns(currentEpisodes);
//Act
mocker.Resolve<EpisodeProvider>().RefreshEpisodeInfo(fakeSeries);
//Assert
mocker.GetMock<IRepository>().Verify(
c => c.AddMany(It.Is<IEnumerable<Episode>>(e => e.Count() == fakeEpisodes.Episodes.Count)), Times.Once());
mocker.GetMock<IRepository>().Verify(c => c.UpdateMany(It.Is<IEnumerable<Episode>>(e => e.Count() == 0)),
Times.AtMostOnce());
mocker.GetMock<IDatabase>().Verify(c => c.Insert(It.IsAny<Object>()), Times.Exactly(tvdbSeries.Episodes.Count));
mocker.GetMock<IDatabase>().Verify(c => c.Update(It.IsAny<Object>()), Times.Never());
mocker.VerifyAllMocks();
}
[Test]
public void existing_episodes_only_calls_UpdateMany()
public void existing_episodes_only_calls_Update()
{
const int seriesId = 71663;
var fakeEpisodes = Builder<TvdbSeries>.CreateNew()
var tvdbSeries = Builder<TvdbSeries>.CreateNew()
.With(c => c.Episodes = new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(5).Build())
).With(c => c.Id = seriesId).Build();
var fakeSeries = Builder<Series>.CreateNew().With(c => c.SeriesId = seriesId).Build();
var currentEpisodes = new List<Episode>();
foreach (var tvDbEpisode in tvdbSeries.Episodes)
{
currentEpisodes.Add(new Episode { TvDbEpisodeId = tvDbEpisode.Id });
}
var mocker = new AutoMoqer();
mocker.GetMock<TvDbProvider>(MockBehavior.Strict)
.Setup(c => c.GetSeries(seriesId, true))
.Returns(fakeEpisodes);
.Returns(tvdbSeries);
mocker.GetMock<IRepository>()
.Setup(c => c.Single(It.IsAny<Expression<Func<Episode, bool>>>()))
.Returns(Builder<Episode>.CreateNew().Build);
mocker.GetMock<IDatabase>()
.Setup(d => d.Fetch<Episode>(It.IsAny<String>(), It.IsAny<Object[]>()))
.Returns(currentEpisodes);
//Act
mocker.Resolve<EpisodeProvider>().RefreshEpisodeInfo(fakeSeries);
//Assert
mocker.GetMock<IRepository>().Verify(c => c.AddMany(It.Is<IEnumerable<Episode>>(e => e.Count() == 0)),
Times.AtMostOnce());
mocker.GetMock<IRepository>().Verify(
c => c.UpdateMany(It.Is<IEnumerable<Episode>>(e => e.Count() == fakeEpisodes.Episodes.Count)),
Times.Once());
mocker.GetMock<IDatabase>().Verify(c => c.Insert(It.IsAny<Object>()), Times.Never());
mocker.GetMock<IDatabase>().Verify(c => c.Update(It.IsAny<Object>()), Times.Exactly(tvdbSeries.Episodes.Count));
mocker.VerifyAllMocks();
}
@ -128,7 +159,7 @@ namespace NzbDrone.Core.Test
public void should_try_to_get_existing_episode_using_tvdbid_first()
{
const int seriesId = 71663;
var fakeEpisodes = Builder<TvdbSeries>.CreateNew()
var fakeTvDbResult = Builder<TvdbSeries>.CreateNew()
.With(c => c.Id = seriesId)
.With(c => c.Episodes = new List<TvdbEpisode>(
Builder<TvdbEpisode>.CreateListOfSize(1)
@ -137,33 +168,31 @@ namespace NzbDrone.Core.Test
)
.Build();
var fakeEpisodeList = new List<Episode> { new Episode { TvDbEpisodeId = 99, SeasonNumber = 10, EpisodeNumber = 10 } };
var fakeSeries = Builder<Series>.CreateNew().With(c => c.SeriesId = seriesId).Build();
var mocker = new AutoMoqer();
mocker.GetMock<IDatabase>()
.Setup(d => d.Fetch<Episode>(It.IsAny<String>(), It.IsAny<Object[]>()))
.Returns(fakeEpisodeList);
var repo = MockLib.GetEmptyRepository();
repo.Add<Episode>(
Builder<Episode>.CreateNew().With(c => c.TvDbEpisodeId = fakeEpisodes.Episodes[0].Id).Build());
mocker.SetConstant(repo);
mocker.GetMock<TvDbProvider>(MockBehavior.Strict)
mocker.GetMock<TvDbProvider>()
.Setup(c => c.GetSeries(seriesId, true))
.Returns(fakeEpisodes);
.Returns(fakeTvDbResult);
//Act
mocker.Resolve<EpisodeProvider>().RefreshEpisodeInfo(fakeSeries);
//Assert
mocker.VerifyAllMocks();
repo.All<Episode>().Should().HaveCount(1);
mocker.GetMock<IDatabase>().Verify(c => c.Update(fakeEpisodeList[0]), Times.Once());
}
[Test]
public void should_try_to_get_existing_episode_using_tvdbid_first_then_season_episode()
{
const int seriesId = 71663;
var fakeEpisodes = Builder<TvdbSeries>.CreateNew()
var tvdbSeries = Builder<TvdbSeries>.CreateNew()
.With(c => c.Id = seriesId)
.With(c => c.Episodes = new List<TvdbEpisode>{
Builder<TvdbEpisode>.CreateNew()
@ -187,20 +216,20 @@ namespace NzbDrone.Core.Test
var mocker = new AutoMoqer();
var repo = MockLib.GetEmptyRepository();
repo.Add<Episode>(localEpisode);
mocker.SetConstant(repo);
mocker.GetMock<TvDbProvider>(MockBehavior.Strict)
.Setup(c => c.GetSeries(seriesId, true))
.Returns(fakeEpisodes);
.Returns(tvdbSeries);
mocker.GetMock<IDatabase>()
.Setup(d => d.Fetch<Episode>(It.IsAny<String>(), It.IsAny<Object[]>()))
.Returns(new List<Episode> { localEpisode });
//Act
mocker.Resolve<EpisodeProvider>().RefreshEpisodeInfo(fakeSeries);
//Assert
mocker.VerifyAllMocks();
repo.All<Episode>().Should().HaveCount(1);
mocker.GetMock<IDatabase>().Verify(c => c.Update(localEpisode), Times.Once());
}
@ -208,51 +237,43 @@ namespace NzbDrone.Core.Test
public void existing_episodes_keep_their_episodeId_file_id()
{
const int seriesId = 71663;
var faketvDbResponse = Builder<TvdbSeries>.CreateNew()
var tvdbSeries = Builder<TvdbSeries>.CreateNew()
.With(c => c.Episodes = new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(5).Build())
).With(c => c.Id = seriesId).Build();
var fakeSeries = Builder<Series>.CreateNew().With(c => c.SeriesId = seriesId).Build();
var fakeEpisode =
Builder<Episode>.CreateNew().With(c => c.EpisodeFileId = 69).And(c => c.EpisodeId = 99).Build();
var currentEpisodes = new List<Episode>();
foreach (var tvDbEpisode in tvdbSeries.Episodes)
{
currentEpisodes.Add(new Episode { TvDbEpisodeId = tvDbEpisode.Id, EpisodeId = 99, EpisodeFileId = 69, Ignored = true });
}
var mocker = new AutoMoqer();
mocker.GetMock<TvDbProvider>(MockBehavior.Strict)
.Setup(c => c.GetSeries(seriesId, true))
.Returns(faketvDbResponse);
.Returns(tvdbSeries);
IEnumerable<Episode> updatedEpisodes = null;
var updatedEpisodes = new List<Episode>();
mocker.GetMock<IRepository>()
.Setup(c => c.Single(It.IsAny<Expression<Func<Episode, bool>>>()))
.Returns(fakeEpisode);
mocker.GetMock<IDatabase>()
.Setup(d => d.Fetch<Episode>(It.IsAny<String>(), It.IsAny<Object[]>()))
.Returns(currentEpisodes);
mocker.GetMock<IRepository>()
.Setup(c => c.UpdateMany(It.IsAny<IEnumerable<Episode>>()))
.Returns(faketvDbResponse.Episodes.Count)
.Callback<IEnumerable<Episode>>(r => updatedEpisodes = r);
mocker.GetMock<IDatabase>()
.Setup(c => c.Update(It.IsAny<Episode>()))
.Returns(1)
.Callback<Episode>(ep => updatedEpisodes.Add(ep));
//Act
mocker.Resolve<EpisodeProvider>().RefreshEpisodeInfo(fakeSeries);
//Assert
mocker.GetMock<IRepository>().Verify(c => c.AddMany(It.Is<IEnumerable<Episode>>(e => e.Count() == 0)),
Times.AtMostOnce());
mocker.GetMock<IRepository>().Verify(
c => c.UpdateMany(It.Is<IEnumerable<Episode>>(e => e.Count() == faketvDbResponse.Episodes.Count)),
Times.Once());
mocker.GetMock<IRepository>().Verify(
c =>
c.UpdateMany(
It.Is<IEnumerable<Episode>>(
e => e.Where(g => g.EpisodeFileId == 69).Count() == faketvDbResponse.Episodes.Count)),
Times.Once());
updatedEpisodes.Should().HaveSameCount(faketvDbResponse.Episodes);
updatedEpisodes.Should().HaveSameCount(tvdbSeries.Episodes);
updatedEpisodes.Should().OnlyContain(c => c.EpisodeId == 99);
updatedEpisodes.Should().OnlyContain(c => c.EpisodeFileId == 69);
updatedEpisodes.Should().OnlyContain(c => c.Ignored == true);
}
@ -347,7 +368,7 @@ namespace NzbDrone.Core.Test
public void Add_daily_show_episodes()
{
var mocker = new AutoMoqer();
mocker.SetConstant(MockLib.GetEmptyRepository());
mocker.SetConstant(MockLib.GetEmptyDatabase());
mocker.Resolve<TvDbProvider>();
const int tvDbSeriesId = 71256;
//act

View File

@ -14,6 +14,7 @@ namespace NzbDrone.Core.Test
{
[TestFixture]
// ReSharper disable InconsistentNaming
[Ignore]
public class DbBenchmark : TestBase
{
const int Episodes_Per_Season = 20;
@ -90,7 +91,7 @@ namespace NzbDrone.Core.Test
[Test]
public void get_episode_by_series_seasons_episode_x5000()
{
var epProvider = new EpisodeProvider(repo, null);
var epProvider = new EpisodeProvider(null, null);
Thread.Sleep(1000);
@ -114,7 +115,7 @@ namespace NzbDrone.Core.Test
[Test]
public void get_episode_by_series_seasons_x1000()
{
var epProvider = new EpisodeProvider(repo, null);
var epProvider = new EpisodeProvider( null, null);
Thread.Sleep(1000);

View File

@ -1,6 +1,5 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Web.Hosting;
@ -9,14 +8,10 @@ using NLog;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Instrumentation;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Providers.ExternalNotification;
using NzbDrone.Core.Providers.Indexer;
using NzbDrone.Core.Providers.Jobs;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
using PetaPoco;
using SubSonic.DataProviders;
using SubSonic.Repository;
namespace NzbDrone.Core
@ -73,30 +68,8 @@ namespace NzbDrone.Core
Logger.Debug("Binding Ninject's Kernel");
_kernel = new StandardKernel();
//dbProvider.Log = new NlogWriter();
_kernel.Bind<QualityProvider>().ToSelf().InSingletonScope();
_kernel.Bind<TvDbProvider>().ToSelf().InTransientScope();
_kernel.Bind<HttpProvider>().ToSelf().InSingletonScope();
_kernel.Bind<SeriesProvider>().ToSelf().InSingletonScope();
_kernel.Bind<EpisodeProvider>().ToSelf().InSingletonScope();
_kernel.Bind<UpcomingEpisodesProvider>().ToSelf().InSingletonScope();
_kernel.Bind<DiskProvider>().ToSelf().InSingletonScope();
_kernel.Bind<SabProvider>().ToSelf().InSingletonScope();
_kernel.Bind<HistoryProvider>().ToSelf().InSingletonScope();
_kernel.Bind<RootDirProvider>().ToSelf().InSingletonScope();
_kernel.Bind<ExternalNotificationProvider>().ToSelf().InSingletonScope();
_kernel.Bind<XbmcProvider>().ToSelf().InSingletonScope();
_kernel.Bind<ConfigProvider>().To<ConfigProvider>().InSingletonScope();
_kernel.Bind<NotificationProvider>().ToSelf().InSingletonScope();
_kernel.Bind<LogProvider>().ToSelf().InSingletonScope();
_kernel.Bind<MediaFileProvider>().ToSelf().InSingletonScope();
_kernel.Bind<JobProvider>().ToSelf().InSingletonScope();
_kernel.Bind<IndexerProvider>().ToSelf().InSingletonScope();
_kernel.Bind<WebTimer>().ToSelf().InSingletonScope();
_kernel.Bind<AutoConfigureProvider>().ToSelf().InSingletonScope();
_kernel.Bind<IDatabase>().ToMethod(c => Connection.GetPetaPocoDb(Connection.MainConnectionString)).InRequestScope();
_kernel.Bind<IRepository>().ToConstant(Connection.CreateSimpleRepository(Connection.MainConnectionString)).InSingletonScope();
_kernel.Bind<IDatabase>().ToConstant(Connection.GetPetaPocoDb(Connection.MainConnectionString)).InRequestScope();
_kernel.Bind<IRepository>().ToConstant(Connection.CreateSimpleRepository(Connection.LogConnectionString)).WhenInjectedInto<SubsonicTarget>().InSingletonScope();
_kernel.Bind<IRepository>().ToConstant(Connection.CreateSimpleRepository(Connection.LogConnectionString)).WhenInjectedInto<LogProvider>().InSingletonScope();
}
@ -104,10 +77,10 @@ namespace NzbDrone.Core
private static void BindIndexers()
{
_kernel.Bind<IndexerBase>().To<NzbsOrg>().InSingletonScope();
_kernel.Bind<IndexerBase>().To<NzbMatrix>().InSingletonScope();
_kernel.Bind<IndexerBase>().To<NzbsRUs>().InSingletonScope();
_kernel.Bind<IndexerBase>().To<Newzbin>().InSingletonScope();
_kernel.Bind<IndexerBase>().To<NzbsOrg>().InTransientScope();
_kernel.Bind<IndexerBase>().To<NzbMatrix>().InTransientScope();
_kernel.Bind<IndexerBase>().To<NzbsRUs>().InTransientScope();
_kernel.Bind<IndexerBase>().To<Newzbin>().InTransientScope();
var indexers = _kernel.GetAll<IndexerBase>();
_kernel.Get<IndexerProvider>().InitializeIndexers(indexers.ToList());

View File

@ -11,7 +11,8 @@ namespace NzbDrone.Core.Datastore
if ((SourceType == typeof(Int32) || SourceType == typeof(Int64)) && destinationInfo.Type.IsGenericType && destinationInfo.Type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
// If it is NULLABLE, then get the underlying type. eg if "Nullable<int>" then this will return just "int"
if (destinationInfo.Type.GetGenericArguments()[0].IsEnum)
Type genericArgument = destinationInfo.Type.GetGenericArguments()[0];
if (genericArgument == typeof(DayOfWeek))
{
return delegate(object s)
{
@ -25,6 +26,20 @@ namespace NzbDrone.Core.Datastore
return (Nullable<DayOfWeek>)value;
};
}
else
{
return delegate(object s)
{
int value;
Int32.TryParse(s.ToString(), out value);
if (value == 0)
{
return null;
}
return value;
};
}
}
return base.GetFromDbConverter(destinationInfo, SourceType);

View File

@ -27,6 +27,25 @@ namespace NzbDrone.Core.Datastore.Migrations
.WithNotNullableColumn("SeasonFolder", DbType.Boolean)
.WithNullableColumn("LastInfoSync", DbType.DateTime)
.WithNullableColumn("LastDiskSync", DbType.DateTime);
db.CreateTable("Episodes")
.WithPrimaryKeyColumn("EpisodeId", DbType.Int32).AsIdentity()
.WithNullableColumn("TvDbEpisodeId", DbType.Int32)
.WithNotNullableColumn("SeriesId", DbType.Int32)
.WithNotNullableColumn("SeasonNumber", DbType.Int16)
.WithNotNullableColumn("EpisodeNumber", DbType.Int16)
.WithNotNullableColumn("Title", DbType.String).HavingDefault(String.Empty)
.WithNotNullableColumn("Overview", DbType.String).HavingDefault(String.Empty)
.WithNotNullableColumn("Ignored", DbType.Boolean).HavingDefault(false)
.WithNullableColumn("EpisodeFileId", DbType.Int32)
.WithNullableColumn("AirDate", DbType.DateTime)
.WithNullableColumn("GrabDate", DbType.DateTime);
}
}
}

View File

@ -26,7 +26,6 @@ using System.Linq.Expressions;
// ReSharper disable
namespace PetaPoco
{
// Poco's marked [Explicit] require all column properties to be marked
[AttributeUsage(AttributeTargets.Class)]
@ -354,12 +353,16 @@ namespace PetaPoco
{
_sharedConnection = _factory.CreateConnection();
_sharedConnection.ConnectionString = _connectionString;
_sharedConnection.Open();
if (KeepConnectionAlive)
_sharedConnectionDepth++; // Make sure you call Dispose
}
if (_sharedConnection.State != ConnectionState.Open)
_sharedConnection.Open();
_sharedConnectionDepth++;
}
// Close a previously opened connection
@ -860,9 +863,6 @@ namespace PetaPoco
var pd = PocoData.ForType(typeof(T));
try
{
if (_sharedConnection.State != ConnectionState.Open)
_sharedConnection.Open();
r = cmd.ExecuteReader();
OnExecutedCommand(cmd);
}
@ -1297,8 +1297,6 @@ namespace PetaPoco
{
using (var cmd = CreateCommand(_sharedConnection, ""))
{
if(_sharedConnection.State != ConnectionState.Open)
_sharedConnection.Open();
var pd = PocoData.ForObject(poco, primaryKeyName);
var names = new List<string>();

View File

@ -185,7 +185,7 @@
<Compile Include="Instrumentation\SubsonicTarget.cs" />
<Compile Include="Instrumentation\ExceptioneerTarget.cs" />
<Compile Include="Instrumentation\NlogWriter.cs" />
<Compile Include="Models\PetaPoco.cs" />
<Compile Include="Datastore\PetaPoco\PetaPoco.cs" />
<Compile Include="Model\ConnectionInfoModel.cs" />
<Compile Include="Model\ExternalNotificationType.cs" />
<Compile Include="Model\LanguageType.cs" />
@ -306,6 +306,9 @@
<ItemGroup>
<WCFMetadata Include="Service References\" />
</ItemGroup>
<ItemGroup>
<Folder Include="Models\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -14,14 +14,12 @@ namespace NzbDrone.Core.Providers
public class EpisodeProvider
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private readonly IRepository _repository;
private readonly TvDbProvider _tvDbProvider;
private readonly IDatabase _database;
[Inject]
public EpisodeProvider(IRepository repository, TvDbProvider tvDbProviderProvider, IDatabase database)
public EpisodeProvider(TvDbProvider tvDbProviderProvider, IDatabase database)
{
_repository = repository;
_tvDbProvider = tvDbProviderProvider;
_database = database;
}
@ -32,36 +30,32 @@ namespace NzbDrone.Core.Providers
public virtual void AddEpisode(Episode episode)
{
_repository.Add(episode);
_database.Insert(episode);
}
public virtual Episode GetEpisode(long id)
{
return _repository.Single<Episode>(id);
return _database.Single<Episode>(id);
}
public virtual Episode GetEpisode(int seriesId, int seasonNumber, int episodeNumber)
{
return
_repository.Single<Episode>(
c => c.SeriesId == seriesId && c.SeasonNumber == seasonNumber && c.EpisodeNumber == episodeNumber);
return _database.Single<Episode>("WHERE SeriesId = @0 AND SeasonNumber = @2 AND EpisodeNumber = @3", seriesId, seasonNumber, episodeNumber);
}
public virtual Episode GetEpisode(int seriesId, DateTime date)
{
return
_repository.Single<Episode>(
c => c.SeriesId == seriesId && c.AirDate == date.Date);
return _database.Single<Episode>("WHERE SeriesId = @0 AND AirDate = @2", seriesId, date.Date);
}
public virtual IEnumerable<Episode> GetEpisodeBySeries(long seriesId)
public virtual IList<Episode> GetEpisodeBySeries(long seriesId)
{
return _database.Query<Episode>("WHERE SeriesId = @0", seriesId);
return _database.Fetch<Episode>("WHERE SeriesId = @0", seriesId);
}
public virtual IList<Episode> GetEpisodesBySeason(long seriesId, int seasonNumber)
{
return _repository.Find<Episode>(e => e.SeriesId == seriesId && e.SeasonNumber == seasonNumber);
return _database.Fetch<Episode>("WHERE SeriesId = @0 AND SeasonNumber = @1", seriesId, seasonNumber);
}
public virtual List<Episode> GetEpisodes(EpisodeParseResult parseResult)
@ -89,15 +83,17 @@ namespace NzbDrone.Core.Providers
public virtual IList<Episode> EpisodesWithoutFiles(bool includeSpecials)
{
var episodes = _database.Query<Episode>("WHERE (EpisodeFileId=0 OR EpisodeFileId=NULL) AND AirDate<=@0",
DateTime.Now.Date);
if (includeSpecials)
return _repository.All<Episode>().Where(e => e.EpisodeFileId == 0 && e.AirDate <= DateTime.Today && e.AirDate > new DateTime(1899, 12, 31)).ToList();
return episodes.Where(e => e.SeasonNumber > 0).ToList();
return _repository.All<Episode>().Where(e => e.EpisodeFileId == 0 && e.AirDate <= DateTime.Today && e.AirDate > new DateTime(1899, 12, 31) && e.SeasonNumber > 0).ToList();
return episodes.ToList();
}
public virtual IList<Episode> EpisodesByFileId(int episodeFileId)
{
return _repository.All<Episode>().Where(e => e.EpisodeFileId == episodeFileId).ToList();
return _database.Fetch<Episode>("WHERE EpisodeFileId = @0", episodeFileId);
}
public virtual void RefreshEpisodeInfo(Series series)
@ -107,6 +103,7 @@ namespace NzbDrone.Core.Providers
int failCount = 0;
var tvDbSeriesInfo = _tvDbProvider.GetSeries(series.SeriesId, true);
var seriesEpisodes = GetEpisodeBySeries(series.SeriesId);
var updateList = new List<Episode>();
var newList = new List<Episode>();
@ -124,12 +121,12 @@ namespace NzbDrone.Core.Providers
Logger.Trace("Updating info for [{0}] - S{1}E{2}", tvDbSeriesInfo.SeriesName, episode.SeasonNumber, episode.EpisodeNumber);
//first check using tvdbId, this should cover cases when and episode number in a season is changed
var episodeToUpdate = _repository.Single<Episode>(c => c.TvDbEpisodeId == episode.Id);
var episodeToUpdate = seriesEpisodes.Where(e => e.TvDbEpisodeId == episode.Id).FirstOrDefault();
//not found, try using season/episode number
if (episodeToUpdate == null)
{
episodeToUpdate = GetEpisode(series.SeriesId, episode.SeasonNumber, episode.EpisodeNumber);
episodeToUpdate = seriesEpisodes.Where(e => e.SeasonNumber == episode.SeasonNumber && e.EpisodeNumber == episode.EpisodeNumber).FirstOrDefault();
}
//Episode doesn't exist locally
@ -161,31 +158,45 @@ namespace NzbDrone.Core.Providers
}
}
_repository.AddMany(newList);
_repository.UpdateMany(updateList);
using (var tran = _database.GetTransaction())
{
newList.ForEach(episode => _database.Insert(episode));
updateList.ForEach(episode => _database.Update(episode));
#if DEBUG
//Shouldn't run if Database is a mock since transaction will be null
if (_database.GetType().Namespace != "Castle.Proxies" && tran != null)
{
tran.Complete();
}
#else
tran.Complete();
#endif
}
Logger.Debug("Finished episode refresh for series:{0}. Successful:{1} - Failed:{2} ",
tvDbSeriesInfo.SeriesName, successCount, failCount);
}
public virtual void DeleteEpisode(int episodeId)
{
_repository.Delete<Episode>(episodeId);
}
public virtual void UpdateEpisode(Episode episode)
{
_repository.Update(episode);
_database.Update(episode);
}
public virtual bool IsIgnored(int seriesId, int seasonNumber)
{
return !_repository.Exists<Episode>(e => e.SeriesId == seriesId && e.SeasonNumber == seasonNumber && !e.Ignored);
var unIgnoredCount = _database.ExecuteScalar<int>(
"SELECT COUNT (*) FROM Episodes WHERE SeriesId=@0 AND SeasonNumber=@1 AND Ignored=False");
return unIgnoredCount != 0;
}
public virtual IList<int> GetSeasons(int seriesId)
{
return _repository.All<Episode>().Where(e => e.SeriesId == seriesId).Select(s => s.SeasonNumber).Distinct().OrderBy(c => c).ToList();
return _database.Fetch<Int32>("SELECT DISTINCT SeasonNumber FROM Episodes WHERE SeriesId=@0", seriesId).OrderBy(c => c).ToList();
}
public virtual void SetSeasonIgnore(long seriesId, int seasonNumber, bool isIgnored)
@ -193,14 +204,27 @@ namespace NzbDrone.Core.Providers
Logger.Info("Setting ignore flag on Series:{0} Season:{1} to {2}", seriesId, seasonNumber, isIgnored);
var episodes = GetEpisodesBySeason(seriesId, seasonNumber);
using (var tran = _database.GetTransaction())
{
foreach (var episode in episodes)
{
episode.Ignored = isIgnored;
_database.Update(episode);
}
_repository.UpdateMany(episodes);
#if DEBUG
//Shouldn't run if Database is a mock since transaction will be null
if (_database.GetType().Namespace != "Castle.Proxies" && tran != null)
{
tran.Complete();
}
#else
tran.Complete();
#endif
Logger.Info("Ignore flag for Series:{0} Season:{1} successfully set to {2}", seriesId, seasonNumber, isIgnored);
}
}
}
}

View File

@ -7,7 +7,8 @@ using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Repository
{
[PetaPoco.TableName("Episodes")]
[TableName("Episodes")]
[PrimaryKey("EpisodeId", autoIncrement = true)]
public class Episode
{
[SubSonicPrimaryKey]