diff --git a/.gitignore b/.gitignore index 5a23bee56..9cec3fceb 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,5 @@ _ReSharper*/ #NZBDrone specific *.db *Web.Publish.xml -NzbDrone.Web/NzbDrone.Web.Publish.xml \ No newline at end of file +NzbDrone.Web/NzbDrone.Web.Publish.xml +*.sdf \ No newline at end of file diff --git a/NzbDrone.5.1.ReSharper b/NzbDrone.5.1.ReSharper index a23a81a3a..ef107f44c 100644 --- a/NzbDrone.5.1.ReSharper +++ b/NzbDrone.5.1.ReSharper @@ -70,4 +70,75 @@ + + + Replace with FluentAssertion + $arg$.Should().BeTrue(); + + + + + + + + Replace with FluentAssertion + $arg$.Should().BeFalse(); + + + + + + + + $actual$.Should().Be($excpected$); + + + False + False + False + Never + + + + + + + + $excpected$.Should().Be($actual$); + + + + + + + + + $arg$.Should().NotBeNull(); + Assert.IsNotNull($arg$); + + + + + + + $arg$.Should().NotBeEmpty(); + Assert.IsNotEmpty($arg$); + + + + + + + $arg$.Should().BeEmpty(); + Assert.IsEmpty($arg$); + + + + + + \ No newline at end of file diff --git a/NzbDrone.Core.Test/EpisodeProviderTest.cs b/NzbDrone.Core.Test/EpisodeProviderTest.cs index 2dea94e39..6b6da3c27 100644 --- a/NzbDrone.Core.Test/EpisodeProviderTest.cs +++ b/NzbDrone.Core.Test/EpisodeProviderTest.cs @@ -284,6 +284,46 @@ namespace NzbDrone.Core.Test mocker.VerifyAllMocks(); } + [Test] + public void RefreshEpisodeInfo_should_set_older_than_1900_to_null() + { + //Arrange + const int seriesId = 71663; + + var fakeEpisodes = Builder.CreateNew().With( + c => c.Episodes = + new List(Builder.CreateListOfSize(10). + WhereAll() + .Have(l => l.Language = new TvdbLanguage(0, "eng", "a")) + .WhereTheFirst(7).Have(e => e.FirstAired = new DateTime(1800, 1, 1)) + .AndTheRemaining().Have(e => e.FirstAired = DateTime.Now) + .Build()) + ).With(c => c.Id = seriesId).Build(); + + var fakeSeries = Builder.CreateNew().With(c => c.SeriesId = seriesId).Build(); + + + var mocker = new AutoMoqer(); + + mocker.SetConstant(MockLib.GetEmptyDatabase()); + + mocker.GetMock() + .Setup(c => c.GetSeries(seriesId, true)) + .Returns(fakeEpisodes); + + + //Act + mocker.Resolve().RefreshEpisodeInfo(fakeSeries); + + //Assert + var storedEpisodes = mocker.Resolve().GetEpisodeBySeries(seriesId).ToList(); + storedEpisodes.Should().HaveCount(10); + storedEpisodes.Where(e => e.AirDate == null).Should().HaveCount(7); + storedEpisodes.Where(e => e.AirDate != null).Should().HaveCount(3); + + mocker.VerifyAllMocks(); + } + [Test] public void new_episodes_only_calls_Insert() { @@ -595,7 +635,7 @@ namespace NzbDrone.Core.Test var db = MockLib.GetEmptyDatabase(); mocker.SetConstant(db); - + //Act var episode = mocker.Resolve().GetEpisode(1, 1, 1); @@ -660,7 +700,7 @@ namespace NzbDrone.Core.Test episode.EpisodeFile.Should().BeNull(); } - + [Test] @@ -683,7 +723,7 @@ namespace NzbDrone.Core.Test .Returns(fakeSeries); //Act - var episode = mocker.Resolve().GetEpisode(1, fakeEpisodes[0].AirDate); + var episode = mocker.Resolve().GetEpisode(1, fakeEpisodes[0].AirDate.Value); //Assert episode.ShouldHave().AllPropertiesBut(e => e.Series, e => e.EpisodeFile).EqualTo(fakeEpisodes.First()); @@ -709,7 +749,7 @@ namespace NzbDrone.Core.Test .Returns(fakeSeries); //Act - var episode = mocker.Resolve().GetEpisode(1, fakeEpisodes[0].AirDate); + var episode = mocker.Resolve().GetEpisode(1, fakeEpisodes[0].AirDate.Value); //Assert episode.ShouldHave().AllPropertiesBut(e => e.Series).EqualTo(fakeEpisodes.First()); @@ -718,6 +758,6 @@ namespace NzbDrone.Core.Test } - + } } \ No newline at end of file diff --git a/NzbDrone.Core.Test/EpisodeStatusTest.cs b/NzbDrone.Core.Test/EpisodeStatusTest.cs index ec7996299..c4c551015 100644 --- a/NzbDrone.Core.Test/EpisodeStatusTest.cs +++ b/NzbDrone.Core.Test/EpisodeStatusTest.cs @@ -2,6 +2,7 @@ // ReSharper disable RedundantUsingDirective using System; using FizzWare.NBuilder; +using FluentAssertions; using NUnit.Framework; using NzbDrone.Core.Model; using NzbDrone.Core.Repository; @@ -107,14 +108,14 @@ namespace NzbDrone.Core.Test public void low_air_date() { Episode episode = Builder.CreateNew() - .With(e => e.AirDate = DateTime.Now.AddYears(-200)) + .With(e => e.AirDate = DateTime.Now.AddDays(20)) .With(e => e.Ignored = false) .With(e => e.EpisodeFileId = 0) .With(e => e.GrabDate = null) .Build(); - Assert.AreEqual(EpisodeStatusType.NotAired, episode.Status); + episode.Status.Should().Be(EpisodeStatusType.NotAired); } } } \ No newline at end of file diff --git a/NzbDrone.Core.Test/Framework/Fixtures.cs b/NzbDrone.Core.Test/Framework/Fixtures.cs index 877489974..156fa50c2 100644 --- a/NzbDrone.Core.Test/Framework/Fixtures.cs +++ b/NzbDrone.Core.Test/Framework/Fixtures.cs @@ -13,7 +13,7 @@ namespace NzbDrone.Core.Test [TearDown] public void TearDown() { - var filesToDelete = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.db", SearchOption.AllDirectories); + var filesToDelete = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.sdf", SearchOption.AllDirectories); foreach (var file in filesToDelete) { try diff --git a/NzbDrone.Core.Test/Framework/MockLib.cs b/NzbDrone.Core.Test/Framework/MockLib.cs index 4ebf70d29..a68f47568 100644 --- a/NzbDrone.Core.Test/Framework/MockLib.cs +++ b/NzbDrone.Core.Test/Framework/MockLib.cs @@ -29,7 +29,7 @@ namespace NzbDrone.Core.Test.Framework if (String.IsNullOrWhiteSpace(fileName)) { - fileName = Guid.NewGuid() + ".db"; + fileName = Guid.NewGuid() + ".sdf"; } var connectionString = Connection.GetConnectionString(fileName); diff --git a/NzbDrone.Core.Test/HistoryProviderTest.cs b/NzbDrone.Core.Test/HistoryProviderTest.cs index f127b89e3..72e391de3 100644 --- a/NzbDrone.Core.Test/HistoryProviderTest.cs +++ b/NzbDrone.Core.Test/HistoryProviderTest.cs @@ -145,14 +145,13 @@ namespace NzbDrone.Core.Test var result = mocker.Resolve().GetBestQualityInHistory(history.EpisodeId); //Assert - Assert.IsNotNull(result); + result.Should().NotBeNull(); result.QualityType.Should().Be(QualityTypes.Bluray720p); } [Test] public void add_item() { - //Arange var mocker = new AutoMoqer(); var db = MockLib.GetEmptyDatabase(); @@ -181,13 +180,14 @@ namespace NzbDrone.Core.Test var storedHistory = db.Fetch(); storedHistory.Should().HaveCount(1); - Assert.AreEqual(history.Date, storedHistory.First().Date); - Assert.AreEqual(history.EpisodeId, storedHistory.First().EpisodeId); - Assert.AreEqual(history.SeriesId, storedHistory.First().SeriesId); - Assert.AreEqual(history.NzbTitle, storedHistory.First().NzbTitle); - Assert.AreEqual(history.Indexer, storedHistory.First().Indexer); - Assert.AreEqual(history.Quality, storedHistory.First().Quality); - Assert.AreEqual(history.IsProper, storedHistory.First().IsProper); + history.Date.Should().BeWithin(TimeSpan.FromMinutes(1)).Before(storedHistory.First().Date); + + history.EpisodeId.Should().Be(storedHistory.First().EpisodeId); + history.SeriesId.Should().Be(storedHistory.First().SeriesId); + history.NzbTitle.Should().Be(storedHistory.First().NzbTitle); + history.Indexer.Should().Be(storedHistory.First().Indexer); + history.Quality.Should().Be(storedHistory.First().Quality); + history.IsProper.Should().Be(storedHistory.First().IsProper); } } } \ No newline at end of file diff --git a/NzbDrone.Core.Test/InventoryProvider_QualityNeededTest.cs b/NzbDrone.Core.Test/InventoryProvider_QualityNeededTest.cs index 3bf61ff62..455c71e33 100644 --- a/NzbDrone.Core.Test/InventoryProvider_QualityNeededTest.cs +++ b/NzbDrone.Core.Test/InventoryProvider_QualityNeededTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using AutoMoq; using FizzWare.NBuilder; +using FluentAssertions; using Moq; using NUnit.Framework; using NzbDrone.Core.Model; @@ -193,7 +194,7 @@ namespace NzbDrone.Core.Test bool result = mocker.Resolve().IsQualityNeeded(parseResultSingle); //Assert - Assert.IsTrue(result); + result.Should().BeTrue(); mocker.VerifyAllMocks(); } @@ -219,7 +220,7 @@ namespace NzbDrone.Core.Test bool result = mocker.Resolve().IsQualityNeeded(parseResultSingle); //Assert - Assert.IsTrue(result); + result.Should().BeTrue(); mocker.VerifyAllMocks(); } diff --git a/NzbDrone.Core.Test/JobProviderTest.cs b/NzbDrone.Core.Test/JobProviderTest.cs index f7ce7b08a..d46dfeb1a 100644 --- a/NzbDrone.Core.Test/JobProviderTest.cs +++ b/NzbDrone.Core.Test/JobProviderTest.cs @@ -33,7 +33,7 @@ namespace NzbDrone.Core.Test var settings = timerProvider.All(); Assert.IsNotEmpty(settings); Assert.AreNotEqual(DateTime.MinValue, settings[0].LastExecution); - Assert.IsTrue(settings[0].Success); + settings[0].Success.Should().BeTrue(); } [Test] @@ -75,9 +75,8 @@ namespace NzbDrone.Core.Test var firstRun = timerProvider.RunScheduled(); var secondRun = timerProvider.RunScheduled(); - Assert.IsTrue(firstRun); - Assert.IsTrue(secondRun); - + firstRun.Should().BeTrue(); + secondRun.Should().BeTrue(); } [Test] @@ -97,9 +96,8 @@ namespace NzbDrone.Core.Test Thread.Sleep(2000); var secondRun = timerProvider.QueueJob(typeof(FakeJob)); - Assert.IsTrue(firstRun); - Assert.IsTrue(secondRun); - + firstRun.Should().BeTrue(); + secondRun.Should().BeTrue(); } [Test] @@ -142,8 +140,8 @@ namespace NzbDrone.Core.Test Thread.Sleep(2000); var secondRun = timerProvider.QueueJob(typeof(BrokenJob)); - Assert.IsTrue(firstRun); - Assert.IsTrue(secondRun); + firstRun.Should().BeTrue(); + secondRun.Should().BeTrue(); Thread.Sleep(2000); ExceptionVerification.ExcpectedErrors(2); } @@ -174,7 +172,7 @@ namespace NzbDrone.Core.Test thread1.Join(); thread2.Join(); - Assert.IsTrue(firstRun); + firstRun.Should().BeTrue(); Assert.IsFalse(secondRun); } @@ -230,13 +228,11 @@ namespace NzbDrone.Core.Test //Assert timers.Should().HaveCount(1); - Assert.AreEqual(fakeTimer.DefaultInterval, timers[0].Interval); - Assert.AreEqual(fakeTimer.Name, timers[0].Name); - Assert.AreEqual(fakeTimer.GetType().ToString(), timers[0].TypeName); - Assert.AreEqual(DateTime.MinValue, timers[0].LastExecution); - Assert.IsTrue(timers[0].Enable); - - + timers[0].Interval.Should().Be(fakeTimer.DefaultInterval); + timers[0].Name.Should().Be(fakeTimer.Name); + timers[0].TypeName.Should().Be(fakeTimer.GetType().ToString()); + timers[0].LastExecution.Should().HaveYear(2000); + timers[0].Enable.Should().BeTrue(); } [Test] @@ -267,7 +263,7 @@ namespace NzbDrone.Core.Test //Assert timers.Should().HaveCount(1); - Assert.IsTrue(timers[0].Enable); + timers[0].Enable.Should().BeTrue(); } [Test] @@ -364,8 +360,8 @@ namespace NzbDrone.Core.Test //Assert var settings = timerProvider.All(); - Assert.IsNotEmpty(settings); - Assert.AreEqual(DateTime.MinValue, settings[0].LastExecution); + settings.Should().NotBeEmpty(); + settings[0].LastExecution.Should().HaveYear(2000); } [Test] diff --git a/NzbDrone.Core.Test/LogProviderTest.cs b/NzbDrone.Core.Test/LogProviderTest.cs index 35564a072..3a3b981b5 100644 --- a/NzbDrone.Core.Test/LogProviderTest.cs +++ b/NzbDrone.Core.Test/LogProviderTest.cs @@ -39,11 +39,10 @@ namespace NzbDrone.Core.Test //Assert db.Fetch().Should().HaveCount(1); - var logItem = db.Fetch().First(); + var logItem = db.Fetch().First(); Assert.AreNotEqual(new DateTime(), logItem.Time); Assert.AreEqual(message, logItem.Message); Assert.AreEqual(Logger.Name, logItem.Logger); - Assert.AreEqual(Logger.Name, logItem.Logger); Assert.AreEqual(LogLevel.Info.Name, logItem.Level); Assert.AreEqual("write_log", logItem.Method); } @@ -149,14 +148,14 @@ namespace NzbDrone.Core.Test } - + [Test] public void null_string_as_arg_should_not_fail() { //setup - + Logger Logger = LogManager.GetCurrentClassLogger(); var epFile = new EpisodeFile(); Logger.Trace("File {0} no longer exists on disk. removing from database.", epFile.Path); diff --git a/NzbDrone.Core.Test/QualityTest.cs b/NzbDrone.Core.Test/QualityTest.cs index 63bedfea7..42743d1c1 100644 --- a/NzbDrone.Core.Test/QualityTest.cs +++ b/NzbDrone.Core.Test/QualityTest.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using FluentAssertions; +using NUnit.Framework; using NzbDrone.Core.Model; using NzbDrone.Core.Repository.Quality; using NzbDrone.Core.Test.Framework; @@ -55,9 +56,9 @@ namespace NzbDrone.Core.Test var first = new Quality(QualityTypes.Bluray1080p, true); var second = new Quality(QualityTypes.Bluray1080p, true); - Assert.IsTrue(first == second); - Assert.IsTrue(first >= second); - Assert.IsTrue(first <= second); + (first == second).Should().BeTrue(); + (first >= second).Should().BeTrue(); + (first <= second).Should().BeTrue(); } [Test] @@ -66,7 +67,7 @@ namespace NzbDrone.Core.Test var first = new Quality(QualityTypes.Bluray1080p, true); var second = new Quality(QualityTypes.Unknown, true); - Assert.IsFalse(first == second); + (first == second).Should().BeFalse(); } [Test] @@ -75,7 +76,7 @@ namespace NzbDrone.Core.Test var first = new Quality(QualityTypes.Bluray1080p, true); var second = new Quality(QualityTypes.Bluray1080p, false); - Assert.IsFalse(first == second); + (first == second).Should().BeFalse(); } @@ -94,7 +95,7 @@ namespace NzbDrone.Core.Test var first = new Quality(QualityTypes.Bluray1080p, true); var second = new Quality(QualityTypes.Unknown, true); - Assert.IsTrue(first != second); + (first != second).Should().BeTrue(); } [Test] @@ -103,7 +104,7 @@ namespace NzbDrone.Core.Test var first = new Quality(QualityTypes.Bluray1080p, true); var second = new Quality(QualityTypes.Bluray1080p, false); - Assert.IsTrue(first != second); + (first != second).Should().BeTrue(); } [Test] @@ -112,8 +113,8 @@ namespace NzbDrone.Core.Test var first = new Quality(QualityTypes.DVD, true); var second = new Quality(QualityTypes.Bluray1080p, true); - Assert.IsTrue(first < second); - Assert.IsTrue(first <= second); + (first < second).Should().BeTrue(); + (first <= second).Should().BeTrue(); } [Test] @@ -122,8 +123,8 @@ namespace NzbDrone.Core.Test var first = new Quality(QualityTypes.DVD, true); var second = new Quality(QualityTypes.Bluray1080p, true); - Assert.IsTrue(second > first); - Assert.IsTrue(second >= first); + (second > first).Should().BeTrue(); + (second >= first).Should().BeTrue(); } } diff --git a/NzbDrone.Core.Test/RootDirProviderTest.cs b/NzbDrone.Core.Test/RootDirProviderTest.cs index 7b492462c..b529b1fde 100644 --- a/NzbDrone.Core.Test/RootDirProviderTest.cs +++ b/NzbDrone.Core.Test/RootDirProviderTest.cs @@ -54,10 +54,9 @@ namespace NzbDrone.Core.Test //Assert var rootDirs = rootDirProvider.GetAll(); - Assert.IsNotEmpty(rootDirs); - + rootDirs.Should().NotBeEmpty(); rootDirs.Should().HaveCount(1); - Assert.AreEqual(path, rootDirs.First().Path); + path.Should().Be(rootDirs.First().Path); } @@ -77,9 +76,8 @@ namespace NzbDrone.Core.Test //Assert var rootDirs = rootDirProvider.GetAll(); - Assert.IsNotEmpty(rootDirs); rootDirs.Should().HaveCount(1); - Assert.AreEqual(newPath, rootDirs.First().Path); + newPath.Should().Be(rootDirs.First().Path); } [Test] @@ -115,8 +113,8 @@ namespace NzbDrone.Core.Test //Assert var rootDir = rootDirProvider.GetRootDir(id); - Assert.AreEqual(1, rootDir.Id); - Assert.AreEqual(path, rootDir.Path); + rootDir.Id.Should().Be(1); + rootDir.Path.Should().Be(path); } [Test] @@ -130,8 +128,8 @@ namespace NzbDrone.Core.Test var result = mocker.Resolve().GetUnmappedFolders(path); - Assert.IsNotNull(result); - Assert.IsEmpty(result); + result.Should().NotBeNull(); + result.Should().BeEmpty(); mocker.VerifyAllMocks(); } diff --git a/NzbDrone.Core.Test/SabProviderTest.cs b/NzbDrone.Core.Test/SabProviderTest.cs index 92d8c3c90..4bc15f101 100644 --- a/NzbDrone.Core.Test/SabProviderTest.cs +++ b/NzbDrone.Core.Test/SabProviderTest.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using AutoMoq; using FizzWare.NBuilder; +using FluentAssertions; using Moq; using NUnit.Framework; using NzbDrone.Core.Model; @@ -63,7 +64,7 @@ namespace NzbDrone.Core.Test "http://www.nzbclub.com/nzb_download.aspx?mid=1950232", "This is an Nzb"); //Assert - Assert.IsTrue(result); + result.Should().BeTrue(); } @@ -110,7 +111,7 @@ namespace NzbDrone.Core.Test "http://www.newzbin.com/browse/post/6107863/nzb", "This is an Nzb"); //Assert - Assert.IsTrue(result); + result.Should().BeTrue(); } [Test] @@ -187,7 +188,7 @@ namespace NzbDrone.Core.Test bool result = mocker.Resolve().IsInQueue("Ubuntu Test"); //Assert - Assert.IsTrue(result); + result.Should().BeTrue(); } [Test] @@ -332,7 +333,7 @@ namespace NzbDrone.Core.Test "http://www.newzbin.com/browse/post/6107863/nzb", "Added by unit tests."); //Assert - Assert.IsTrue(result); + result.Should().BeTrue(); } } } \ No newline at end of file diff --git a/NzbDrone.Core.Test/SeriesProviderTest.cs b/NzbDrone.Core.Test/SeriesProviderTest.cs index 8e10dfeb6..2b032aa00 100644 --- a/NzbDrone.Core.Test/SeriesProviderTest.cs +++ b/NzbDrone.Core.Test/SeriesProviderTest.cs @@ -202,7 +202,7 @@ namespace NzbDrone.Core.Test //Act, Assert var provider = mocker.Resolve(); - Assert.IsTrue(provider.IsMonitored(12)); + provider.IsMonitored(12).Should().BeTrue(); Assert.IsFalse(provider.IsMonitored(11)); Assert.IsFalse(provider.IsMonitored(1)); } diff --git a/NzbDrone.Core/Datastore/Connection.cs b/NzbDrone.Core/Datastore/Connection.cs index c1a1b2676..ad5ebb48f 100644 --- a/NzbDrone.Core/Datastore/Connection.cs +++ b/NzbDrone.Core/Datastore/Connection.cs @@ -2,6 +2,7 @@ using System.Data; using System.Data.Common; using System.Data.SQLite; +using System.Data.SqlServerCe; using System.IO; using MvcMiniProfiler.Data; using PetaPoco; @@ -21,14 +22,15 @@ namespace NzbDrone.Core.Datastore public static string GetConnectionString(string path) { - return String.Format("Data Source={0};Version=3;Cache Size=30000;Pooling=true;Default Timeout=2", path); + //return String.Format("Data Source={0};Version=3;Cache Size=30000;Pooling=true;Default Timeout=2", path); + return String.Format("Data Source={0}", path); } public static String MainConnectionString { get { - return GetConnectionString(Path.Combine(AppDataPath.FullName, "nzbdrone.db")); + return GetConnectionString(Path.Combine(AppDataPath.FullName, "nzbdrone.sdf")); } } @@ -36,7 +38,7 @@ namespace NzbDrone.Core.Datastore { get { - return GetConnectionString(Path.Combine(AppDataPath.FullName, "log.db")); + return GetConnectionString(Path.Combine(AppDataPath.FullName, "log.sdf")); } } @@ -44,9 +46,9 @@ namespace NzbDrone.Core.Datastore public static IDatabase GetPetaPocoDb(string connectionString, Boolean profiled = true) { MigrationsHelper.Run(connectionString, true); - var sqliteConnection = new SQLiteConnection(connectionString); + var sqliteConnection = new SqlCeConnection(connectionString); DbConnection connection = sqliteConnection; - + if (profiled) { connection = ProfiledDbConnection.Get(sqliteConnection); diff --git a/NzbDrone.Core/Datastore/Migrations/Migration20110619.cs b/NzbDrone.Core/Datastore/Migrations/Migration20110619.cs deleted file mode 100644 index 9be21b431..000000000 --- a/NzbDrone.Core/Datastore/Migrations/Migration20110619.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Data; -using Migrator.Framework; - -namespace NzbDrone.Core.Datastore.Migrations -{ - - [Migration(20110619)] - public class Migration20110619 : Migration - { - public override void Up() - { - if (Database.TableExists("Histories")) - { - Database.RemoveTable("Histories"); - } - } - - public override void Down() - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/NzbDrone.Core/Datastore/Migrations/Migration20110616.cs b/NzbDrone.Core/Datastore/Migrations/Migration20110622.cs similarity index 91% rename from NzbDrone.Core/Datastore/Migrations/Migration20110616.cs rename to NzbDrone.Core/Datastore/Migrations/Migration20110622.cs index 0e70b03b6..94b9e93ff 100644 --- a/NzbDrone.Core/Datastore/Migrations/Migration20110616.cs +++ b/NzbDrone.Core/Datastore/Migrations/Migration20110622.cs @@ -5,8 +5,8 @@ using Migrator.Framework; namespace NzbDrone.Core.Datastore.Migrations { - [Migration(20110604)] - public class Migration20110616 : Migration + [Migration(20110622)] + public class Migration20110622 : Migration { public override void Up() { @@ -17,12 +17,12 @@ namespace NzbDrone.Core.Datastore.Migrations new Column("CleanTitle", DbType.String, ColumnProperty.Null), new Column("Status", DbType.String, ColumnProperty.Null), new Column("Overview", DbType.String, ColumnProperty.Null), - new Column("AirsDayOfWeek", DbType.Int16, ColumnProperty.Null), + new Column("AirsDayOfWeek", DbType.Int32, ColumnProperty.Null), new Column("AirTimes", DbType.String, ColumnProperty.Null), new Column("Language", DbType.String, ColumnProperty.Null), new Column("Path", DbType.String, ColumnProperty.NotNull), new Column("Monitored", DbType.Boolean, ColumnProperty.NotNull), - new Column("QualityProfileId", DbType.Int16, ColumnProperty.NotNull), + new Column("QualityProfileId", DbType.Int32, ColumnProperty.NotNull), new Column("SeasonFolder", DbType.Boolean, ColumnProperty.NotNull), new Column("LastInfoSync", DbType.DateTime, ColumnProperty.Null), new Column("LastDiskSync", DbType.DateTime, ColumnProperty.Null) @@ -33,8 +33,8 @@ namespace NzbDrone.Core.Datastore.Migrations new Column("EpisodeId", DbType.Int32, ColumnProperty.PrimaryKeyWithIdentity), new Column("TvDbEpisodeId", DbType.Int32, ColumnProperty.Null), new Column("SeriesId", DbType.Int32, ColumnProperty.NotNull), - new Column("SeasonNumber", DbType.Int16, ColumnProperty.NotNull), - new Column("EpisodeNumber", DbType.Int16, ColumnProperty.NotNull), + new Column("SeasonNumber", DbType.Int32, ColumnProperty.NotNull), + new Column("EpisodeNumber", DbType.Int32, ColumnProperty.NotNull), new Column("Title", DbType.String, ColumnProperty.Null), new Column("Overview", DbType.String, ColumnProperty.Null), new Column("Ignored", DbType.Boolean, ColumnProperty.NotNull), @@ -50,11 +50,11 @@ namespace NzbDrone.Core.Datastore.Migrations ColumnProperty.PrimaryKeyWithIdentity), new Column("SeriesId", DbType.Int32, ColumnProperty.NotNull), new Column("Path", DbType.String, ColumnProperty.NotNull), - new Column("Quality", DbType.Int16, ColumnProperty.NotNull), - new Column("Proper", DbType.Int16, ColumnProperty.NotNull), + new Column("Quality", DbType.Int32, ColumnProperty.NotNull), + new Column("Proper", DbType.Int32, ColumnProperty.NotNull), new Column("Size", DbType.Int64, ColumnProperty.NotNull), new Column("DateAdded", DbType.DateTime, ColumnProperty.NotNull), - new Column("SeasonNumber", DbType.Int16, ColumnProperty.NotNull) + new Column("SeasonNumber", DbType.Int32, ColumnProperty.NotNull) }); @@ -73,25 +73,25 @@ namespace NzbDrone.Core.Datastore.Migrations Database.AddTable("History", new[] { - new Column("HistoryId", DbType.Int64, ColumnProperty.PrimaryKey), + new Column("HistoryId", DbType.Int64, ColumnProperty.PrimaryKeyWithIdentity), new Column("EpisodeId", DbType.Int32, ColumnProperty.NotNull), new Column("SeriesId", DbType.Int32, ColumnProperty.NotNull), new Column("NzbTitle", DbType.String, ColumnProperty.NotNull), new Column("Date", DbType.DateTime, ColumnProperty.NotNull), - new Column("Quality", DbType.Int16, ColumnProperty.NotNull), + new Column("Quality", DbType.Int32, ColumnProperty.NotNull), new Column("IsProper", DbType.Boolean, ColumnProperty.NotNull), new Column("Indexer", DbType.String, ColumnProperty.NotNull) }); Database.AddTable("RootDirs", new[] { - new Column("Id", DbType.Int32, ColumnProperty.PrimaryKey), + new Column("Id", DbType.Int32, ColumnProperty.PrimaryKeyWithIdentity), new Column("Path", DbType.String, ColumnProperty.NotNull) }); Database.AddTable("ExternalNotificationSettings", new[] { - new Column("Id", DbType.Int32, ColumnProperty.PrimaryKey), + new Column("Id", DbType.Int32, ColumnProperty.PrimaryKeyWithIdentity), new Column("Enabled", DbType.Boolean, ColumnProperty.NotNull), new Column("NotifierName", DbType.String, ColumnProperty.NotNull), new Column("Name", DbType.String, ColumnProperty.NotNull) @@ -99,7 +99,7 @@ namespace NzbDrone.Core.Datastore.Migrations Database.AddTable("JobSettings", new[] { - new Column("Id", DbType.Int32, ColumnProperty.PrimaryKey), + new Column("Id", DbType.Int32, ColumnProperty.PrimaryKeyWithIdentity), new Column("Enable", DbType.Boolean, ColumnProperty.NotNull), new Column("TypeName", DbType.String, ColumnProperty.NotNull), new Column("Name", DbType.String, ColumnProperty.NotNull), @@ -110,7 +110,7 @@ namespace NzbDrone.Core.Datastore.Migrations Database.AddTable("QualityProfiles", new[] { - new Column("QualityProfileId", DbType.Int32, ColumnProperty.PrimaryKey), + new Column("QualityProfileId", DbType.Int32, ColumnProperty.PrimaryKeyWithIdentity), new Column("Name", DbType.String, ColumnProperty.NotNull), new Column("Cutoff", DbType.Int32, ColumnProperty.NotNull), new Column("SonicAllowed", DbType.String, ColumnProperty.NotNull), @@ -118,7 +118,7 @@ namespace NzbDrone.Core.Datastore.Migrations Database.AddTable("Logs", new[] { - new Column("LogId", DbType.Int64, ColumnProperty.PrimaryKey), + new Column("LogId", DbType.Int64, ColumnProperty.PrimaryKeyWithIdentity), new Column("Message", DbType.String, ColumnProperty.NotNull), new Column("Time", DbType.DateTime, ColumnProperty.NotNull), new Column("Logger", DbType.String, ColumnProperty.NotNull), @@ -130,7 +130,7 @@ namespace NzbDrone.Core.Datastore.Migrations Database.AddTable("IndexerSettings", new[] { - new Column("Id", DbType.Int32, ColumnProperty.PrimaryKey), + new Column("Id", DbType.Int32, ColumnProperty.PrimaryKeyWithIdentity), new Column("Enable", DbType.Boolean, ColumnProperty.NotNull), new Column("IndexProviderType", DbType.String, ColumnProperty.NotNull), new Column("Name", DbType.String, ColumnProperty.NotNull), diff --git a/NzbDrone.Core/Datastore/MigrationsHelper.cs b/NzbDrone.Core/Datastore/MigrationsHelper.cs index ed0249417..4ca071790 100644 --- a/NzbDrone.Core/Datastore/MigrationsHelper.cs +++ b/NzbDrone.Core/Datastore/MigrationsHelper.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Data.SqlServerCe; +using System.IO; using System.Reflection; using NLog; @@ -16,6 +18,8 @@ namespace NzbDrone.Core.Datastore if (_migrated.ContainsKey(connetionString)) return; _migrated.Add(connetionString, string.Empty); + EnsureDatabase(connetionString); + Logger.Info("Preparing run database migration"); try @@ -23,11 +27,11 @@ namespace NzbDrone.Core.Datastore Migrator.Migrator migrator; if (trace) { - migrator = new Migrator.Migrator("Sqlite", connetionString, Assembly.GetAssembly(typeof(MigrationsHelper)), true, new MigrationLogger()); + migrator = new Migrator.Migrator("sqlserverce", connetionString, Assembly.GetAssembly(typeof(MigrationsHelper)), true, new MigrationLogger()); } else { - migrator = new Migrator.Migrator("Sqlite", connetionString, Assembly.GetAssembly(typeof(MigrationsHelper))); + migrator = new Migrator.Migrator("sqlserverce", connetionString, Assembly.GetAssembly(typeof(MigrationsHelper))); } @@ -46,8 +50,18 @@ namespace NzbDrone.Core.Datastore } } - + private static void EnsureDatabase(string constr) + { + var connection = new SqlCeConnection(constr); + if (!File.Exists(connection.Database)) + { + var engine = new SqlCeEngine(constr); + engine.CreateDatabase(); + } + } } + + } \ No newline at end of file diff --git a/NzbDrone.Core/Datastore/PetaPoco/PetaPoco.cs b/NzbDrone.Core/Datastore/PetaPoco/PetaPoco.cs index 5a910df6d..e193fdff4 100644 --- a/NzbDrone.Core/Datastore/PetaPoco/PetaPoco.cs +++ b/NzbDrone.Core/Datastore/PetaPoco/PetaPoco.cs @@ -24,6 +24,7 @@ using System.Reflection.Emit; using System.Text; using System.Text.RegularExpressions; using System.Threading; +using MvcMiniProfiler; namespace PetaPoco { @@ -316,7 +317,7 @@ namespace PetaPoco Oracle, SQLite } - DBType _dbType = DBType.SQLite; + DBType _dbType = DBType.SqlServerCE; // Common initialization private void CommonConstruct() @@ -645,28 +646,31 @@ namespace PetaPoco public int Execute(Sql sql) { - try + using (MiniProfiler.StepStatic("Peta Execute SQL")) { - OpenSharedConnection(); try { - using (var cmd = CreateCommand(_sharedConnection, sql)) + OpenSharedConnection(); + try { - var result = cmd.ExecuteNonQuery(); - OnExecutedCommand(cmd); - return result; + using (var cmd = CreateCommand(_sharedConnection, sql)) + { + var result = cmd.ExecuteNonQuery(); + OnExecutedCommand(cmd); + return result; + } + } + finally + { + CloseSharedConnection(); } } - finally + catch (Exception x) { - CloseSharedConnection(); + OnException(x); + throw; } } - catch (Exception x) - { - OnException(x); - throw; - } } // Execute and cast a scalar property @@ -677,28 +681,31 @@ namespace PetaPoco public T ExecuteScalar(Sql sql) { - try + using (MiniProfiler.StepStatic("Peta ExecuteScalar")) { - OpenSharedConnection(); try { - using (var cmd = CreateCommand(_sharedConnection, sql)) + OpenSharedConnection(); + try { - object val = cmd.ExecuteScalar(); - OnExecutedCommand(cmd); - return (T)Convert.ChangeType(val, typeof(T)); + using (var cmd = CreateCommand(_sharedConnection, sql)) + { + object val = cmd.ExecuteScalar(); + OnExecutedCommand(cmd); + return (T)Convert.ChangeType(val, typeof(T)); + } + } + finally + { + CloseSharedConnection(); } } - finally + catch (Exception x) { - CloseSharedConnection(); + OnException(x); + throw; } } - catch (Exception x) - { - OnException(x); - throw; - } } Regex rxSelect = new Regex(@"\A\s*(SELECT|EXECUTE|CALL)\s", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Multiline); @@ -887,50 +894,55 @@ namespace PetaPoco public IEnumerable Query(Sql sql) { - OpenSharedConnection(); - try + using (MiniProfiler.StepStatic("Peta Query SQL")) { - using (var cmd = CreateCommand(_sharedConnection, sql)) + OpenSharedConnection(); + try { - IDataReader r; - var pd = PocoData.ForType(typeof(T)); - try + using (var cmd = CreateCommand(_sharedConnection, sql)) { - r = cmd.ExecuteReader(); - OnExecutedCommand(cmd); - } - catch (Exception x) - { - OnException(x); - throw; - } - - using (r) - { - var factory = pd.GetFactory(cmd.CommandText, _sharedConnection.ConnectionString, ForceDateTimesToUtc, 0, r.FieldCount, r) as Func; - while (true) + IDataReader r; + var pd = PocoData.ForType(typeof(T)); + try { - T poco; - try - { - if (!r.Read()) - yield break; - poco = factory(r); - } - catch (Exception x) - { - OnException(x); - throw; - } + r = cmd.ExecuteReader(); + OnExecutedCommand(cmd); + } + catch (Exception x) + { + OnException(x); + throw; + } - yield return poco; + using (r) + { + var factory = + pd.GetFactory(cmd.CommandText, _sharedConnection.ConnectionString, ForceDateTimesToUtc, 0, r.FieldCount, r) + as Func; + while (true) + { + T poco; + try + { + if (!r.Read()) + yield break; + poco = factory(r); + } + catch (Exception x) + { + OnException(x); + throw; + } + + yield return poco; + } } } } - } - finally - { - CloseSharedConnection(); + finally + { + CloseSharedConnection(); + } } } @@ -1181,62 +1193,65 @@ namespace PetaPoco // Actual implementation of the multi-poco query public IEnumerable Query(Type[] types, object cb, string sql, params object[] args) { - OpenSharedConnection(); - try + using (MiniProfiler.StepStatic("Peta Query Type[]")) { - using (var cmd = CreateCommand(_sharedConnection, sql, args)) + OpenSharedConnection(); + try { - IDataReader r; - try + using (var cmd = CreateCommand(_sharedConnection, sql, args)) { - r = cmd.ExecuteReader(); - OnExecutedCommand(cmd); - } - catch (Exception x) - { - OnException(x); - throw; - } - var factory = GetMultiPocoFactory(types, sql, r); - if (cb == null) - cb = GetAutoMapper(types.ToArray()); - bool bNeedTerminator = false; - using (r) - { - while (true) + IDataReader r; + try { - TRet poco; - try - { - if (!r.Read()) - break; - poco = factory(r, cb); - } - catch (Exception x) - { - OnException(x); - throw; - } - - if (poco != null) - yield return poco; - else - bNeedTerminator = true; + r = cmd.ExecuteReader(); + OnExecutedCommand(cmd); } - if (bNeedTerminator) + catch (Exception x) { - var poco = (TRet)(cb as Delegate).DynamicInvoke(new object[types.Length]); - if (poco != null) - yield return poco; - else - yield break; + OnException(x); + throw; + } + var factory = GetMultiPocoFactory(types, sql, r); + if (cb == null) + cb = GetAutoMapper(types.ToArray()); + bool bNeedTerminator = false; + using (r) + { + while (true) + { + TRet poco; + try + { + if (!r.Read()) + break; + poco = factory(r, cb); + } + catch (Exception x) + { + OnException(x); + throw; + } + + if (poco != null) + yield return poco; + else + bNeedTerminator = true; + } + if (bNeedTerminator) + { + var poco = (TRet)(cb as Delegate).DynamicInvoke(new object[types.Length]); + if (poco != null) + yield return poco; + else + yield break; + } } } } - } - finally - { - CloseSharedConnection(); + finally + { + CloseSharedConnection(); + } } } @@ -1355,172 +1370,175 @@ namespace PetaPoco // the new id is returned. public object Insert(string tableName, string primaryKeyName, bool autoIncrement, object poco) { - try + using (MiniProfiler.StepStatic("Peta Insert " + tableName)) { - OpenSharedConnection(); try { - using (var cmd = CreateCommand(_sharedConnection, "")) + OpenSharedConnection(); + try { - var pd = PocoData.ForObject(poco, primaryKeyName); - var names = new List(); - var values = new List(); - var index = 0; - var versionName = ""; - - foreach (var i in pd.Columns) + using (var cmd = CreateCommand(_sharedConnection, "")) { - // Don't insert result columns - if (i.Value.ResultColumn) - continue; + var pd = PocoData.ForObject(poco, primaryKeyName); + var names = new List(); + var values = new List(); + var index = 0; + var versionName = ""; - // Don't insert the primary key (except under oracle where we need bring in the next sequence value) - if (autoIncrement && primaryKeyName != null && string.Compare(i.Key, primaryKeyName, true) == 0) + foreach (var i in pd.Columns) { - if (_dbType == DBType.Oracle && !string.IsNullOrEmpty(pd.TableInfo.SequenceName)) + // Don't insert result columns + if (i.Value.ResultColumn) + continue; + + // Don't insert the primary key (except under oracle where we need bring in the next sequence value) + if (autoIncrement && primaryKeyName != null && string.Compare(i.Key, primaryKeyName, true) == 0) { - names.Add(i.Key); - values.Add(string.Format("{0}.nextval", pd.TableInfo.SequenceName)); + if (_dbType == DBType.Oracle && !string.IsNullOrEmpty(pd.TableInfo.SequenceName)) + { + names.Add(i.Key); + values.Add(string.Format("{0}.nextval", pd.TableInfo.SequenceName)); + } + continue; } - continue; + + names.Add(EscapeSqlIdentifier(i.Key)); + values.Add(string.Format("{0}{1}", _paramPrefix, index++)); + + object val = i.Value.GetValue(poco); + if (i.Value.VersionColumn) + { + val = 1; + versionName = i.Key; + } + + AddParam(cmd, val, _paramPrefix); } - names.Add(EscapeSqlIdentifier(i.Key)); - values.Add(string.Format("{0}{1}", _paramPrefix, index++)); - - object val = i.Value.GetValue(poco); - if (i.Value.VersionColumn) - { - val = 1; - versionName = i.Key; - } - - AddParam(cmd, val, _paramPrefix); - } - - cmd.CommandText = string.Format("INSERT INTO {0} ({1}) VALUES ({2})", - EscapeTableName(tableName), - string.Join(",", names.ToArray()), - string.Join(",", values.ToArray()) + cmd.CommandText = string.Format("INSERT INTO {0} ({1}) VALUES ({2})", + EscapeTableName(tableName), + string.Join(",", names.ToArray()), + string.Join(",", values.ToArray()) ); - if (!autoIncrement) - { - DoPreExecute(cmd); - cmd.ExecuteNonQuery(); - OnExecutedCommand(cmd); - return true; - } - - object id; - - switch (_dbType) - { - case DBType.SqlServerCE: + if (!autoIncrement) + { DoPreExecute(cmd); cmd.ExecuteNonQuery(); OnExecutedCommand(cmd); - id = ExecuteScalar("SELECT @@@IDENTITY AS NewID;"); - break; - case DBType.SqlServer: - cmd.CommandText += ";\nSELECT SCOPE_IDENTITY() AS NewID;"; - DoPreExecute(cmd); - id = cmd.ExecuteScalar(); - OnExecutedCommand(cmd); - break; - case DBType.PostgreSQL: - if (primaryKeyName != null) - { - cmd.CommandText += string.Format("returning {0} as NewID", EscapeSqlIdentifier(primaryKeyName)); + return true; + } + + object id; + + switch (_dbType) + { + case DBType.SqlServerCE: + DoPreExecute(cmd); + cmd.ExecuteNonQuery(); + OnExecutedCommand(cmd); + id = ExecuteScalar("SELECT @@@IDENTITY AS NewID;"); + break; + case DBType.SqlServer: + cmd.CommandText += ";\nSELECT SCOPE_IDENTITY() AS NewID;"; DoPreExecute(cmd); id = cmd.ExecuteScalar(); - } - else - { - id = -1; - DoPreExecute(cmd); - cmd.ExecuteNonQuery(); - } - OnExecutedCommand(cmd); - break; - case DBType.Oracle: - if (primaryKeyName != null) - { - cmd.CommandText += string.Format(" returning {0} into :newid", EscapeSqlIdentifier(primaryKeyName)); - var param = cmd.CreateParameter(); - param.ParameterName = ":newid"; - param.Value = DBNull.Value; - param.Direction = ParameterDirection.ReturnValue; - param.DbType = DbType.Int64; - cmd.Parameters.Add(param); - DoPreExecute(cmd); - cmd.ExecuteNonQuery(); - id = param.Value; - } - else - { - id = -1; - DoPreExecute(cmd); - cmd.ExecuteNonQuery(); - } - OnExecutedCommand(cmd); - break; - case DBType.SQLite: - if (primaryKeyName != null) - { - cmd.CommandText += ";\nSELECT last_insert_rowid();"; + OnExecutedCommand(cmd); + break; + case DBType.PostgreSQL: + if (primaryKeyName != null) + { + cmd.CommandText += string.Format("returning {0} as NewID", EscapeSqlIdentifier(primaryKeyName)); + DoPreExecute(cmd); + id = cmd.ExecuteScalar(); + } + else + { + id = -1; + DoPreExecute(cmd); + cmd.ExecuteNonQuery(); + } + OnExecutedCommand(cmd); + break; + case DBType.Oracle: + if (primaryKeyName != null) + { + cmd.CommandText += string.Format(" returning {0} into :newid", EscapeSqlIdentifier(primaryKeyName)); + var param = cmd.CreateParameter(); + param.ParameterName = ":newid"; + param.Value = DBNull.Value; + param.Direction = ParameterDirection.ReturnValue; + param.DbType = DbType.Int64; + cmd.Parameters.Add(param); + DoPreExecute(cmd); + cmd.ExecuteNonQuery(); + id = param.Value; + } + else + { + id = -1; + DoPreExecute(cmd); + cmd.ExecuteNonQuery(); + } + OnExecutedCommand(cmd); + break; + case DBType.SQLite: + if (primaryKeyName != null) + { + cmd.CommandText += ";\nSELECT last_insert_rowid();"; + DoPreExecute(cmd); + id = cmd.ExecuteScalar(); + } + else + { + id = -1; + DoPreExecute(cmd); + cmd.ExecuteNonQuery(); + } + OnExecutedCommand(cmd); + break; + default: + cmd.CommandText += ";\nSELECT @@IDENTITY AS NewID;"; DoPreExecute(cmd); id = cmd.ExecuteScalar(); - } - else + OnExecutedCommand(cmd); + break; + } + + // Assign the ID back to the primary key property + if (primaryKeyName != null) + { + PocoColumn pc; + if (pd.Columns.TryGetValue(primaryKeyName, out pc)) { - id = -1; - DoPreExecute(cmd); - cmd.ExecuteNonQuery(); + pc.SetValue(poco, pc.ChangeType(id)); } - OnExecutedCommand(cmd); - break; - default: - cmd.CommandText += ";\nSELECT @@IDENTITY AS NewID;"; - DoPreExecute(cmd); - id = cmd.ExecuteScalar(); - OnExecutedCommand(cmd); - break; - } - - // Assign the ID back to the primary key property - if (primaryKeyName != null) - { - PocoColumn pc; - if (pd.Columns.TryGetValue(primaryKeyName, out pc)) - { - pc.SetValue(poco, pc.ChangeType(id)); } - } - // Assign the Version column - if (!string.IsNullOrEmpty(versionName)) - { - PocoColumn pc; - if (pd.Columns.TryGetValue(versionName, out pc)) + // Assign the Version column + if (!string.IsNullOrEmpty(versionName)) { - pc.SetValue(poco, pc.ChangeType(1)); + PocoColumn pc; + if (pd.Columns.TryGetValue(versionName, out pc)) + { + pc.SetValue(poco, pc.ChangeType(1)); + } } - } - return id; + return id; + } + } + finally + { + CloseSharedConnection(); } } - finally + catch (Exception x) { - CloseSharedConnection(); + OnException(x); + throw; } } - catch (Exception x) - { - OnException(x); - throw; - } } // Insert an annotated poco object @@ -1546,95 +1564,102 @@ namespace PetaPoco // Update a record with values from a poco. primary key value can be either supplied or read from the poco public int Update(string tableName, string primaryKeyName, object poco, object primaryKeyValue) { - try + using (MiniProfiler.StepStatic("Peta Update " + tableName)) { - OpenSharedConnection(); try { - using (var cmd = CreateCommand(_sharedConnection, "")) + OpenSharedConnection(); + try { - var sb = new StringBuilder(); - var index = 0; - var pd = PocoData.ForObject(poco, primaryKeyName); - string versionName = null; - object versionValue = null; - - var primaryKeyValuePairs = GetPrimaryKeyValues(primaryKeyName, primaryKeyValue); - - foreach (var i in pd.Columns) + using (var cmd = CreateCommand(_sharedConnection, "")) { - // Don't update the primary key, but grab the value if we don't have it - if (primaryKeyValue == null && primaryKeyValuePairs.ContainsKey(i.Key)) + var sb = new StringBuilder(); + var index = 0; + var pd = PocoData.ForObject(poco, primaryKeyName); + string versionName = null; + object versionValue = null; + + var primaryKeyValuePairs = GetPrimaryKeyValues(primaryKeyName, primaryKeyValue); + + foreach (var i in pd.Columns) { - primaryKeyValuePairs[i.Key] = i.Value.PropertyInfo.GetValue(poco, null); - continue; + // Don't update the primary key, but grab the value if we don't have it + if (primaryKeyValue == null && primaryKeyValuePairs.ContainsKey(i.Key)) + { + primaryKeyValuePairs[i.Key] = i.Value.PropertyInfo.GetValue(poco, null); + continue; + } + + // Dont update result only columns + if (i.Value.ResultColumn) + continue; + + object value = i.Value.PropertyInfo.GetValue(poco, null); + + if (i.Value.VersionColumn) + { + versionName = i.Key; + versionValue = value; + value = Convert.ToInt64(value) + 1; + } + + // Build the sql + if (index > 0) + sb.Append(", "); + sb.AppendFormat("{0} = {1}{2}", EscapeSqlIdentifier(i.Key), _paramPrefix, index++); + + // Store the parameter in the command + AddParam(cmd, value, _paramPrefix); } - // Dont update result only columns - if (i.Value.ResultColumn) - continue; + cmd.CommandText = string.Format("UPDATE {0} SET {1} WHERE {2}", + EscapeSqlIdentifier(tableName), sb.ToString(), + BuildPrimaryKeySql(primaryKeyValuePairs, ref index)); - object value = i.Value.PropertyInfo.GetValue(poco, null); - - if (i.Value.VersionColumn) + foreach (var keyValue in primaryKeyValuePairs) { - versionName = i.Key; - versionValue = value; - value = Convert.ToInt64(value) + 1; + AddParam(cmd, keyValue.Value, _paramPrefix); } - // Build the sql - if (index > 0) - sb.Append(", "); - sb.AppendFormat("{0} = {1}{2}", EscapeSqlIdentifier(i.Key), _paramPrefix, index++); - - // Store the parameter in the command - AddParam(cmd, value, _paramPrefix); - } - - cmd.CommandText = string.Format("UPDATE {0} SET {1} WHERE {2}", - EscapeSqlIdentifier(tableName), sb.ToString(), BuildPrimaryKeySql(primaryKeyValuePairs, ref index)); - - foreach (var keyValue in primaryKeyValuePairs) - { - AddParam(cmd, keyValue.Value, _paramPrefix); - } - - if (!string.IsNullOrEmpty(versionName)) - { - cmd.CommandText += string.Format(" AND {0} = {1}{2}", EscapeSqlIdentifier(versionName), _paramPrefix, index++); - AddParam(cmd, versionValue, _paramPrefix); - } - - DoPreExecute(cmd); - - // Do it - var result = cmd.ExecuteNonQuery(); - OnExecutedCommand(cmd); - - // Set Version - if (!string.IsNullOrEmpty(versionName)) - { - PocoColumn pc; - if (pd.Columns.TryGetValue(versionName, out pc)) + if (!string.IsNullOrEmpty(versionName)) { - pc.PropertyInfo.SetValue(poco, Convert.ChangeType(Convert.ToInt64(versionValue) + 1, pc.PropertyInfo.PropertyType), null); + cmd.CommandText += string.Format(" AND {0} = {1}{2}", EscapeSqlIdentifier(versionName), _paramPrefix, + index++); + AddParam(cmd, versionValue, _paramPrefix); } - } - return result; + DoPreExecute(cmd); + + // Do it + var result = cmd.ExecuteNonQuery(); + OnExecutedCommand(cmd); + + // Set Version + if (!string.IsNullOrEmpty(versionName)) + { + PocoColumn pc; + if (pd.Columns.TryGetValue(versionName, out pc)) + { + pc.PropertyInfo.SetValue(poco, + Convert.ChangeType(Convert.ToInt64(versionValue) + 1, + pc.PropertyInfo.PropertyType), null); + } + } + + return result; + } + } + finally + { + CloseSharedConnection(); } } - finally + catch (Exception x) { - CloseSharedConnection(); + OnException(x); + throw; } } - catch (Exception x) - { - OnException(x); - throw; - } } private string BuildPrimaryKeySql(Dictionary primaryKeyValuePair, ref int index) diff --git a/NzbDrone.Core/Instrumentation/SubsonicTarget.cs b/NzbDrone.Core/Instrumentation/SubsonicTarget.cs index 261be609c..ff9a2a3fe 100644 --- a/NzbDrone.Core/Instrumentation/SubsonicTarget.cs +++ b/NzbDrone.Core/Instrumentation/SubsonicTarget.cs @@ -1,10 +1,12 @@ using System; using NLog; using NLog.Targets; +using NLog.Targets.Wrappers; using PetaPoco; namespace NzbDrone.Core.Instrumentation { + public class SubsonicTarget : Target { private readonly IDatabase _database; @@ -14,6 +16,8 @@ namespace NzbDrone.Core.Instrumentation _database = database; } + + protected override void Write(LogEventInfo logEvent) { var log = new Log(); diff --git a/NzbDrone.Core/Model/EpisodeParseResult.cs b/NzbDrone.Core/Model/EpisodeParseResult.cs index 9c9818d82..c374cd3ff 100644 --- a/NzbDrone.Core/Model/EpisodeParseResult.cs +++ b/NzbDrone.Core/Model/EpisodeParseResult.cs @@ -7,14 +7,14 @@ namespace NzbDrone.Core.Model public class EpisodeParseResult { internal string CleanTitle { get; set; } - + public string EpisodeTitle { get; set; } internal int SeasonNumber { get; set; } internal List EpisodeNumbers { get; set; } - internal DateTime AirDate { get; set; } + internal DateTime? AirDate { get; set; } public Quality Quality { get; set; } @@ -30,11 +30,14 @@ namespace NzbDrone.Core.Model public override string ToString() { - if (EpisodeNumbers == null) - return string.Format("{0} - {1} {2}", CleanTitle, AirDate.ToShortDateString(), Quality); + if (AirDate != null && EpisodeNumbers == null) + return string.Format("{0} - {1} {2}", CleanTitle, AirDate.Value.ToShortDateString(), Quality); - return string.Format("{0} - S{1:00}E{2} {3}", CleanTitle, SeasonNumber, - String.Join("-", EpisodeNumbers), Quality); + if (EpisodeNumbers != null) + return string.Format("{0} - S{1:00}E{2} {3}", CleanTitle, SeasonNumber, + String.Join("-", EpisodeNumbers), Quality); + + return NzbTitle; } } diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index a4b8db683..6bf38e5a4 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -159,6 +159,7 @@ False ..\Libraries\System.Data.SQLite.dll + @@ -176,8 +177,7 @@ - - + diff --git a/NzbDrone.Core/Providers/Core/ConfigProvider.cs b/NzbDrone.Core/Providers/Core/ConfigProvider.cs index 298cb0738..2555c3d86 100644 --- a/NzbDrone.Core/Providers/Core/ConfigProvider.cs +++ b/NzbDrone.Core/Providers/Core/ConfigProvider.cs @@ -278,7 +278,7 @@ namespace NzbDrone.Core.Providers.Core { string value; - var dbValue = _database.SingleOrDefault("WHERE Key=@0", key); + var dbValue = _database.SingleOrDefault("WHERE [Key] =@0", key); if (dbValue != null && !String.IsNullOrEmpty(dbValue.Value)) return dbValue.Value; @@ -308,7 +308,7 @@ namespace NzbDrone.Core.Providers.Core Logger.Debug("Writing Setting to file. Key:'{0}' Value:'{1}'", key, value); - var dbValue = _database.SingleOrDefault("WHERE KEY=@0", key); + var dbValue = _database.SingleOrDefault("WHERE [KEY]=@0", key); if (dbValue == null) { @@ -317,7 +317,11 @@ namespace NzbDrone.Core.Providers.Core else { dbValue.Value = value; - _database.Update(dbValue); + using (var tran = _database.GetTransaction()) + { + _database.Update(dbValue); + tran.Complete(); + } } } } diff --git a/NzbDrone.Core/Providers/EpisodeProvider.cs b/NzbDrone.Core/Providers/EpisodeProvider.cs index 08e9526a3..3296cb16b 100644 --- a/NzbDrone.Core/Providers/EpisodeProvider.cs +++ b/NzbDrone.Core/Providers/EpisodeProvider.cs @@ -113,9 +113,9 @@ namespace NzbDrone.Core.Providers foreach (var episodeNumber in parseResult.EpisodeNumbers) { var episodeInfo = GetEpisode(parseResult.Series.SeriesId, parseResult.SeasonNumber, episodeNumber); - if (episodeInfo == null) + if (episodeInfo == null && parseResult.AirDate != null) { - episodeInfo = GetEpisode(parseResult.Series.SeriesId, parseResult.AirDate); + episodeInfo = GetEpisode(parseResult.Series.SeriesId, parseResult.AirDate.Value); } //if still null we should add the temp episode if (episodeInfo == null && autoAddNew) @@ -209,12 +209,16 @@ namespace NzbDrone.Core.Providers episodeToUpdate.SeriesId = series.SeriesId; episodeToUpdate.TvDbEpisodeId = episode.Id; - episodeToUpdate.AirDate = episode.FirstAired.Date; episodeToUpdate.EpisodeNumber = episode.EpisodeNumber; episodeToUpdate.SeasonNumber = episode.SeasonNumber; episodeToUpdate.Title = episode.EpisodeName; episodeToUpdate.Overview = episode.Overview; + if (episode.FirstAired.Year > 1900) + { + episodeToUpdate.AirDate = episode.FirstAired.Date; + } + successCount++; } catch (Exception e) diff --git a/NzbDrone.Core/Providers/Jobs/JobProvider.cs b/NzbDrone.Core/Providers/Jobs/JobProvider.cs index da6c054e4..ed19fa093 100644 --- a/NzbDrone.Core/Providers/Jobs/JobProvider.cs +++ b/NzbDrone.Core/Providers/Jobs/JobProvider.cs @@ -292,7 +292,7 @@ namespace NzbDrone.Core.Providers.Jobs TypeName = timer.GetType().ToString(), Name = timerProviderLocal.Name, Interval = timerProviderLocal.DefaultInterval, - LastExecution = DateTime.MinValue + LastExecution = new DateTime(2000, 1, 1) }; SaveSettings(settings); diff --git a/NzbDrone.Core/Providers/MediaFileProvider.cs b/NzbDrone.Core/Providers/MediaFileProvider.cs index 2429cd71b..991a90d15 100644 --- a/NzbDrone.Core/Providers/MediaFileProvider.cs +++ b/NzbDrone.Core/Providers/MediaFileProvider.cs @@ -72,7 +72,7 @@ namespace NzbDrone.Core.Providers { var allEpisodes = _episodeProvider.GetEpisodeBySeries(seriesId).ToList(); - var episodeTotal = allEpisodes.Where(e => !e.Ignored && e.AirDate <= DateTime.Today && e.AirDate.Year > 1900).ToList(); + var episodeTotal = allEpisodes.Where(e => !e.Ignored && e.AirDate != null && e.AirDate <= DateTime.Today).ToList(); var avilableEpisodes = episodeTotal.Where(e => e.EpisodeFileId > 0).ToList(); return new Tuple(avilableEpisodes.Count, episodeTotal.Count); diff --git a/NzbDrone.Core/Providers/SeriesProvider.cs b/NzbDrone.Core/Providers/SeriesProvider.cs index 896f09a02..1bde249df 100644 --- a/NzbDrone.Core/Providers/SeriesProvider.cs +++ b/NzbDrone.Core/Providers/SeriesProvider.cs @@ -49,14 +49,15 @@ namespace NzbDrone.Core.Providers if (!ignoreSpecials) seasonNumber = -1; - var series = _database.Fetch(@"SELECT Series.*, COUNT (NULLIF(Ignored, 1)) AS EpisodeCount, - SUM(CASE WHEN Ignored = 0 AND EpisodeFileId > 0 THEN 1 ELSE 0 END) as EpisodeFileCount, - COUNT (DISTINCT(NULLIF(SeasonNumber, @0))) as SeasonCount, - QualityProfiles.* - FROM Series - INNER JOIN QualityProfiles ON Series.QualityProfileId = QualityProfiles.QualityProfileId - JOIN Episodes ON Series.SeriesId = Episodes.SeriesId - GROUP BY seriesId", seasonNumber); + var series = _database + .Fetch(@"SELECT Series.*, SUM(CASE WHEN Ignored = 0 THEN 1 ELSE 0 END) AS EpisodeCount, +SUM(CASE WHEN Ignored = 0 AND EpisodeFileId > 0 THEN 1 ELSE 0 END) as EpisodeFileCount, +COUNT (DISTINCT(CASE WHEN SeasonNumber = 0 THEN null ELSE SeasonNumber END)) as SeasonCount, +QualityProfiles.* +FROM Series +INNER JOIN QualityProfiles ON Series.QualityProfileId = QualityProfiles.QualityProfileId +JOIN Episodes ON Series.SeriesId = Episodes.SeriesId +GROUP BY seriesId"); return series; } diff --git a/NzbDrone.Core/Repository/Episode.cs b/NzbDrone.Core/Repository/Episode.cs index f5ce16816..18b6173f4 100644 --- a/NzbDrone.Core/Repository/Episode.cs +++ b/NzbDrone.Core/Repository/Episode.cs @@ -17,7 +17,7 @@ namespace NzbDrone.Core.Repository public int SeasonNumber { get; set; } public int EpisodeNumber { get; set; } public string Title { get; set; } - public DateTime AirDate { get; set; } + public DateTime? AirDate { get; set; } public string Overview { get; set; } @@ -47,7 +47,7 @@ namespace NzbDrone.Core.Repository if (Ignored) return EpisodeStatusType.Ignored; - if (AirDate.Date.Year > 1900 && DateTime.Now.Date >= AirDate.Date) + if (AirDate != null && AirDate.Value.Date < DateTime.Now) { return EpisodeStatusType.Missing; } diff --git a/NzbDrone.Web/Controllers/MissingController.cs b/NzbDrone.Web/Controllers/MissingController.cs index 85ff4997d..6b94dce08 100644 --- a/NzbDrone.Web/Controllers/MissingController.cs +++ b/NzbDrone.Web/Controllers/MissingController.cs @@ -37,7 +37,7 @@ namespace NzbDrone.Web.Controllers EpisodeTitle = e.Title, Overview = e.Overview, SeriesTitle = e.Series.Title, - AirDate = e.AirDate, + AirDate = e.AirDate.Value, }); return View(new GridModel(missing)); diff --git a/NzbDrone.Web/Controllers/SeriesController.cs b/NzbDrone.Web/Controllers/SeriesController.cs index ed892ca8f..725eb7b88 100644 --- a/NzbDrone.Web/Controllers/SeriesController.cs +++ b/NzbDrone.Web/Controllers/SeriesController.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Web.Mvc; +using MvcMiniProfiler; using NzbDrone.Core.Providers; using NzbDrone.Core.Providers.Jobs; using NzbDrone.Core.Repository; @@ -119,8 +120,11 @@ namespace NzbDrone.Web.Controllers [GridAction] public ActionResult _AjaxSeasonGrid(int seriesId, int seasonNumber) { - var episodes = GetEpisodeModels(_episodeProvider.GetEpisodesBySeason(seriesId, seasonNumber)); - return View(new GridModel(episodes)); + using (MiniProfiler.StepStatic("Controller")) + { + var episodes = GetEpisodeModels(_episodeProvider.GetEpisodesBySeason(seriesId, seasonNumber)); + return View(new GridModel(episodes)); + } } public ActionResult SearchForSeries(string seriesName) @@ -240,7 +244,7 @@ namespace NzbDrone.Web.Controllers SeasonNumber = e.SeasonNumber, Title = e.Title, Overview = e.Overview, - AirDate = e.AirDate, + AirDate = e.AirDate.Value, Path = episodePath, EpisodeFileId = episodeFileId, Status = e.Status.ToString(), diff --git a/NzbDrone.Web/Controllers/UpcomingController.cs b/NzbDrone.Web/Controllers/UpcomingController.cs index ceaacb5d5..5b463da2f 100644 --- a/NzbDrone.Web/Controllers/UpcomingController.cs +++ b/NzbDrone.Web/Controllers/UpcomingController.cs @@ -37,7 +37,7 @@ namespace NzbDrone.Web.Controllers EpisodeNumber = u.EpisodeNumber, Title = u.Title, Overview = u.Overview, - AirDate = u.AirDate.Add(Convert.ToDateTime(u.Series.AirTimes).TimeOfDay) + AirDate = u.AirDate.Value.Add(Convert.ToDateTime(u.Series.AirTimes).TimeOfDay) }); return View(new GridModel(upcoming)); @@ -55,7 +55,7 @@ namespace NzbDrone.Web.Controllers EpisodeNumber = u.EpisodeNumber, Title = u.Title, Overview = u.Overview, - AirDate = u.AirDate.Add(Convert.ToDateTime(u.Series.AirTimes).TimeOfDay) + AirDate = u.AirDate.Value.Add(Convert.ToDateTime(u.Series.AirTimes).TimeOfDay) }); return View(new GridModel(upcoming)); @@ -73,7 +73,7 @@ namespace NzbDrone.Web.Controllers EpisodeNumber = u.EpisodeNumber, Title = u.Title, Overview = u.Overview, - AirDate = u.AirDate.Add(Convert.ToDateTime(u.Series.AirTimes).TimeOfDay) + AirDate = u.AirDate.Value.Add(Convert.ToDateTime(u.Series.AirTimes).TimeOfDay) }); return View(new GridModel(upcoming)); @@ -91,7 +91,7 @@ namespace NzbDrone.Web.Controllers EpisodeNumber = u.EpisodeNumber, Title = u.Title, Overview = u.Overview, - AirDate = u.AirDate.Add(Convert.ToDateTime(u.Series.AirTimes).TimeOfDay) + AirDate = u.AirDate.Value.Add(Convert.ToDateTime(u.Series.AirTimes).TimeOfDay) }); return View(new GridModel(upcoming)); diff --git a/NzbDrone.Web/Global.asax.cs b/NzbDrone.Web/Global.asax.cs index 8bec6011c..56caffc54 100644 --- a/NzbDrone.Web/Global.asax.cs +++ b/NzbDrone.Web/Global.asax.cs @@ -12,6 +12,7 @@ using Ninject.Web.Mvc; using NLog; using NzbDrone.Core; using NzbDrone.Core.Instrumentation; +using Telerik.Web.Mvc; namespace NzbDrone.Web { @@ -36,7 +37,7 @@ namespace NzbDrone.Web protected override void OnApplicationStarted() { base.OnApplicationStarted(); - + WebAssetDefaultSettings.UseTelerikContentDeliveryNetwork = true; RegisterRoutes(RouteTable.Routes); //base.OnApplicationStarted(); AreaRegistration.RegisterAllAreas(); diff --git a/NzbDrone.Web/Views/Series/Index.cshtml b/NzbDrone.Web/Views/Series/Index.cshtml index 3b7e380b1..5a74b77d1 100644 --- a/NzbDrone.Web/Views/Series/Index.cshtml +++ b/NzbDrone.Web/Views/Series/Index.cshtml @@ -6,36 +6,7 @@ Series } - -