diff --git a/NzbDrone.Core.Test/Datastore/BasicRepositoryFixture.cs b/NzbDrone.Core.Test/Datastore/BasicRepositoryFixture.cs index a15c00c6b..865ce94bb 100644 --- a/NzbDrone.Core.Test/Datastore/BasicRepositoryFixture.cs +++ b/NzbDrone.Core.Test/Datastore/BasicRepositoryFixture.cs @@ -1,44 +1,29 @@ using System; -using System.Data; using System.Linq; using FizzWare.NBuilder; using FluentAssertions; -using Marr.Data.Mapping; using NUnit.Framework; using NzbDrone.Core.Datastore; +using NzbDrone.Core.Jobs; using NzbDrone.Core.Test.Framework; namespace NzbDrone.Core.Test.Datastore { - public class BasicType : ModelBase - { - public string Name { get; set; } - public string Tilte { get; set; } - public string Address { get; set; } - } [TestFixture] - public class - BasicRepositoryFixture : DbTest, BasicType> + public class + BasicRepositoryFixture : DbTest, JobDefinition> { - private BasicType _basicType; + private JobDefinition _basicType; [SetUp] public void Setup() { - _basicType = Builder + _basicType = Builder .CreateNew() .With(c => c.Id = 0) .Build(); - - var mapping = new FluentMappings(true); - - mapping.Entity() - .Columns.AutoMapSimpleTypeProperties() - .For(c => c.Id).SetAutoIncrement() - .SetPrimaryKey(); - } [Test] diff --git a/NzbDrone.Core.Test/Datastore/ObjectDatabaseFixture.cs b/NzbDrone.Core.Test/Datastore/ObjectDatabaseFixture.cs index a42a03470..6b9cf9d2d 100644 --- a/NzbDrone.Core.Test/Datastore/ObjectDatabaseFixture.cs +++ b/NzbDrone.Core.Test/Datastore/ObjectDatabaseFixture.cs @@ -6,19 +6,20 @@ using FizzWare.NBuilder; using FluentAssertions; using NUnit.Framework; using NzbDrone.Core.Datastore; +using NzbDrone.Core.Jobs; using NzbDrone.Core.Test.Framework; namespace NzbDrone.Core.Test.Datastore { [TestFixture] - public class ObjectDatabaseFixture : DbTest, BasicType> + public class ObjectDatabaseFixture : DbTest, JobDefinition> { - private BasicType _sampleType; + private JobDefinition _sampleType; [SetUp] public void SetUp() { - _sampleType = Builder + _sampleType = Builder .CreateNew() .With(s => s.Id = 0) .Build(); @@ -29,7 +30,7 @@ namespace NzbDrone.Core.Test.Datastore public void should_be_able_to_write_to_database() { Subject.Insert(_sampleType); - Db.All().Should().HaveCount(1); + Db.All().Should().HaveCount(1); } [Test] @@ -49,7 +50,7 @@ namespace NzbDrone.Core.Test.Datastore [Test] public void should_be_able_to_store_empty_list() { - var series = new List(); + var series = new List(); Subject.InsertMany(series); } @@ -68,7 +69,7 @@ namespace NzbDrone.Core.Test.Datastore _sampleType.Id = 0; Subject.Insert(_sampleType); - Db.All().Should().HaveCount(1); + Db.All().Should().HaveCount(1); _sampleType.Id.Should().Be(1); } @@ -80,7 +81,7 @@ namespace NzbDrone.Core.Test.Datastore { _sampleType.Id = 0; Subject.Insert(_sampleType); - var item = Db.All(); + var item = Db.All(); item.Should().HaveCount(1); item.First().Id.Should().NotBe(0); @@ -92,7 +93,7 @@ namespace NzbDrone.Core.Test.Datastore public void should_be_able_to_find_object_by_id() { Subject.Insert(_sampleType); - var item = Db.All().Single(c => c.Id == _sampleType.Id); + var item = Db.All().Single(c => c.Id == _sampleType.Id); item.Id.Should().NotBe(0); item.Id.Should().Be(_sampleType.Id); @@ -102,25 +103,25 @@ namespace NzbDrone.Core.Test.Datastore [Test] public void update_field_should_only_update_that_filed() { - var childModel = new BasicType + var childModel = new JobDefinition { - Address = "Address", + Type = "Address", Name = "Name", - Tilte = "Title" + Interval = 12 }; Subject.Insert(childModel); - childModel.Address = "A"; + childModel.Type = "A"; childModel.Name = "B"; - childModel.Tilte = "C"; + childModel.Interval = 0; Subject.UpdateFields(childModel, t => t.Name); - Db.All().Single().Address.Should().Be("Address"); - Db.All().Single().Name.Should().Be("B"); - Db.All().Single().Tilte.Should().Be("Title"); + Db.All().Single().Type.Should().Be("Address"); + Db.All().Single().Name.Should().Be("B"); + Db.All().Single().Interval.Should().Be(12); } diff --git a/NzbDrone.Core.Test/Framework/DbTest.cs b/NzbDrone.Core.Test/Framework/DbTest.cs index 0bc4e78c9..7b3001fb9 100644 --- a/NzbDrone.Core.Test/Framework/DbTest.cs +++ b/NzbDrone.Core.Test/Framework/DbTest.cs @@ -7,6 +7,7 @@ using Marr.Data; using NUnit.Framework; using NzbDrone.Common; using NzbDrone.Core.Datastore; +using NzbDrone.Core.Datastore.Migration.Framework; namespace NzbDrone.Core.Test.Framework { @@ -85,7 +86,7 @@ namespace NzbDrone.Core.Test.Framework MapRepository.Instance.EnableTraceLogging = true; - var factory = new DbFactory(); + var factory = new DbFactory(new MigrationController(new NlogAnnouncer())); _database = factory.Create(_dbName); _db = new TestTestDatabase(_database); Mocker.SetConstant(_database); diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index ace617aae..6321ce1d0 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -79,6 +79,11 @@ ..\packages\MarrDataMapper.3.17.4747.34302\lib\Marr.Data.dll + + ..\packages\FluentMigrator.1.0.6.0\lib\40\FluentMigrator.dll + + + ..\packages\FluentMigrator.1.0.6.0\tools\FluentMigrator.Runner.dll diff --git a/NzbDrone.Core.Test/packages.config b/NzbDrone.Core.Test/packages.config index 03b747121..3f1b7b323 100644 --- a/NzbDrone.Core.Test/packages.config +++ b/NzbDrone.Core.Test/packages.config @@ -4,6 +4,7 @@ + diff --git a/NzbDrone.Core/Datastore/Converters/BooleanIntConverter.cs b/NzbDrone.Core/Datastore/Converters/BooleanIntConverter.cs new file mode 100644 index 000000000..88d06c669 --- /dev/null +++ b/NzbDrone.Core/Datastore/Converters/BooleanIntConverter.cs @@ -0,0 +1,52 @@ +using System; +using Marr.Data.Converters; +using Marr.Data.Mapping; + +namespace NzbDrone.Core.Datastore.Converters +{ + public class BooleanIntConverter : IConverter + { + public object FromDB(ColumnMap map, object dbValue) + { + if (dbValue == DBNull.Value) + { + return DBNull.Value; + } + + var val = (Int64)dbValue; + + switch (val) + { + case 1: + return true; + case 0: + return false; + default: + throw new ConversionException(string.Format("The BooleanCharConverter could not convert the value '{0}' to a Boolean.", dbValue)); + } + } + + public object ToDB(object clrValue) + { + var val = (Nullable)clrValue; + + switch (val) + { + case true: + return 1; + case false: + return 0; + default: + return DBNull.Value; + } + } + + public Type DbType + { + get + { + return typeof(int); + } + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Datastore/Converters/Int32Converter.cs b/NzbDrone.Core/Datastore/Converters/Int32Converter.cs new file mode 100644 index 000000000..fcf66a045 --- /dev/null +++ b/NzbDrone.Core/Datastore/Converters/Int32Converter.cs @@ -0,0 +1,31 @@ +using System; +using Marr.Data.Converters; +using Marr.Data.Mapping; + +namespace NzbDrone.Core.Datastore.Converters +{ + public class Int32Converter : IConverter + { + public object FromDB(ColumnMap map, object dbValue) + { + if (dbValue == DBNull.Value) + { + return DBNull.Value; + } + + if (dbValue is Int32) + { + return dbValue; + } + + return Convert.ToInt32(dbValue); + } + + public object ToDB(object clrValue) + { + return clrValue; + } + + public Type DbType { get; private set; } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Datastore/DbFactory.cs b/NzbDrone.Core/Datastore/DbFactory.cs index 357f3f2f1..bcd2b441f 100644 --- a/NzbDrone.Core/Datastore/DbFactory.cs +++ b/NzbDrone.Core/Datastore/DbFactory.cs @@ -2,35 +2,35 @@ using System.Data; using Marr.Data; using Mono.Data.Sqlite; +using NzbDrone.Core.Datastore.Migration.Framework; namespace NzbDrone.Core.Datastore { public interface IDbFactory { - IDatabase Create(string dbPath = null); + IDatabase Create(string dbPath, MigrationType migrationType = MigrationType.Main); } public class DbFactory : IDbFactory { - private const string MemoryConnectionString = "Data Source=:memory:;Version=3;New=True;"; + private readonly IMigrationController _migrationController; - public IDatabase Create(string dbPath = null) + public DbFactory(IMigrationController migrationController) { - var connectionString = MemoryConnectionString; + TableMapping.Map(); + _migrationController = migrationController; + } - if (!string.IsNullOrWhiteSpace(dbPath)) - { - connectionString = GetConnectionString(dbPath); - } + public IDatabase Create(string dbPath, MigrationType migrationType = MigrationType.Main) + { + var connectionString = GetConnectionString(dbPath); - MigrationHelper.MigrateToLatest(connectionString, MigrationType.Main); + _migrationController.MigrateToLatest(connectionString, migrationType); var dataMapper = new DataMapper(SqliteFactory.Instance, connectionString); return new Database(dataMapper); } - - private string GetConnectionString(string dbPath) { return String.Format("Data Source={0};Version=3;", dbPath); diff --git a/NzbDrone.Core/Datastore/Migration/Framework/MigrationController.cs b/NzbDrone.Core/Datastore/Migration/Framework/MigrationController.cs new file mode 100644 index 000000000..396ad47d1 --- /dev/null +++ b/NzbDrone.Core/Datastore/Migration/Framework/MigrationController.cs @@ -0,0 +1,39 @@ +using System.Reflection; +using FluentMigrator.Runner; +using FluentMigrator.Runner.Initialization; +using NzbDrone.Core.Datastore.Migration.Sqlite; + +namespace NzbDrone.Core.Datastore.Migration.Framework +{ + public interface IMigrationController + { + void MigrateToLatest(string connectionString, MigrationType migrationType); + } + + public class MigrationController : IMigrationController + { + private readonly IAnnouncer _announcer; + + public MigrationController(IAnnouncer announcer) + { + _announcer = announcer; + } + + public void MigrateToLatest(string connectionString, MigrationType migrationType) + { + var assembly = Assembly.GetExecutingAssembly(); + + var migrationContext = new RunnerContext(_announcer) + { + Namespace = "NzbDrone.Core.Datastore.Migration", + ApplicationContext = migrationType + }; + + var options = new MigrationOptions { PreviewOnly = false, Timeout = 60 }; + var factory = new MonoSqliteProcessorFactory(); + var processor = factory.Create(connectionString, _announcer, options); + var runner = new MigrationRunner(assembly, migrationContext, processor); + runner.MigrateUp(true); + } + } +} diff --git a/NzbDrone.Core/Datastore/Migration/Framework/MigrationOptions.cs b/NzbDrone.Core/Datastore/Migration/Framework/MigrationOptions.cs new file mode 100644 index 000000000..10f11336b --- /dev/null +++ b/NzbDrone.Core/Datastore/Migration/Framework/MigrationOptions.cs @@ -0,0 +1,10 @@ +using FluentMigrator; + +namespace NzbDrone.Core.Datastore.Migration.Framework +{ + public class MigrationOptions : IMigrationProcessorOptions + { + public bool PreviewOnly { get; set; } + public int Timeout { get; set; } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Datastore/NlogAnnouncer.cs b/NzbDrone.Core/Datastore/Migration/Framework/NlogAnnouncer.cs similarity index 62% rename from NzbDrone.Core/Datastore/NlogAnnouncer.cs rename to NzbDrone.Core/Datastore/Migration/Framework/NlogAnnouncer.cs index 3599266e3..c108151e8 100644 --- a/NzbDrone.Core/Datastore/NlogAnnouncer.cs +++ b/NzbDrone.Core/Datastore/Migration/Framework/NlogAnnouncer.cs @@ -1,11 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using FluentMigrator.Runner.Announcers; +using FluentMigrator.Runner.Announcers; using NLog; -namespace NzbDrone.Core.Datastore +namespace NzbDrone.Core.Datastore.Migration.Framework { public class NlogAnnouncer : Announcer { diff --git a/NzbDrone.Core/Datastore/Migrations/NzbDroneMigration.cs b/NzbDrone.Core/Datastore/Migration/Framework/NzbDroneMigrationBase.cs similarity index 59% rename from NzbDrone.Core/Datastore/Migrations/NzbDroneMigration.cs rename to NzbDrone.Core/Datastore/Migration/Framework/NzbDroneMigrationBase.cs index a8ab45812..5bb072233 100644 --- a/NzbDrone.Core/Datastore/Migrations/NzbDroneMigration.cs +++ b/NzbDrone.Core/Datastore/Migration/Framework/NzbDroneMigrationBase.cs @@ -1,13 +1,8 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using FluentMigrator; -using NzbDrone.Common; -namespace NzbDrone.Core.Datastore.Migrations +namespace NzbDrone.Core.Datastore.Migration.Framework { - public abstract class NzbDroneMigration : Migration + public abstract class NzbDroneMigrationBase : FluentMigrator.Migration { protected virtual void MainDbUpgrade() { @@ -19,11 +14,11 @@ namespace NzbDrone.Core.Datastore.Migrations public override void Up() { - if ((MigrationType)this.ApplicationContext == MigrationType.Main) + if ((MigrationType)ApplicationContext == MigrationType.Main) { MainDbUpgrade(); } - else if ((MigrationType)this.ApplicationContext == MigrationType.Log) + else if ((MigrationType)ApplicationContext == MigrationType.Log) { LogDbUpgrade(); } diff --git a/NzbDrone.Core/Datastore/Migrations/Migration20130324.cs b/NzbDrone.Core/Datastore/Migration/Migration20130324.cs similarity index 94% rename from NzbDrone.Core/Datastore/Migrations/Migration20130324.cs rename to NzbDrone.Core/Datastore/Migration/Migration20130324.cs index 1911125df..504428e3c 100644 --- a/NzbDrone.Core/Datastore/Migrations/Migration20130324.cs +++ b/NzbDrone.Core/Datastore/Migration/Migration20130324.cs @@ -1,14 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using FluentMigrator; +using FluentMigrator; +using NzbDrone.Core.Datastore.Migration.Framework; -namespace NzbDrone.Core.Datastore.Migrations +namespace NzbDrone.Core.Datastore.Migration { [Tags("")] [Migration(20130324)] - public class Migration20130324 : NzbDroneMigration + public class Migration20130324 : NzbDroneMigrationBase { protected override void MainDbUpgrade() { @@ -80,12 +77,6 @@ namespace NzbDrone.Core.Datastore.Migrations .WithColumn("LastExecution").AsDateTime().NotNullable() .WithColumn("Success").AsBoolean().NotNullable(); - Create.Table("MetadataDefinitions") - .WithColumn("Id").AsInt32().PrimaryKey().Identity() - .WithColumn("Enable").AsBoolean().NotNullable() - .WithColumn("Type").AsString().NotNullable() - .WithColumn("Name").AsString().NotNullable(); - Create.Table("NewznabDefinitions") .WithColumn("Id").AsInt32().PrimaryKey().Identity() .WithColumn("Enable").AsBoolean().NotNullable() diff --git a/NzbDrone.Core/Datastore/Migration/Sqlite/MonoSqliteDbFactory.cs b/NzbDrone.Core/Datastore/Migration/Sqlite/MonoSqliteDbFactory.cs new file mode 100644 index 000000000..9fe5d2234 --- /dev/null +++ b/NzbDrone.Core/Datastore/Migration/Sqlite/MonoSqliteDbFactory.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using FluentMigrator.Runner.Processors; + +namespace NzbDrone.Core.Datastore.Migration.Sqlite +{ + public class MonoSqliteDbFactory : ReflectionBasedDbFactory + { + public MonoSqliteDbFactory() + : base("Mono.Data.Sqlite", "Mono.Data.Sqlite.SqliteFactory") + { + } + + + } +} diff --git a/NzbDrone.Core/Datastore/Migration/Sqlite/MonoSqliteProcessorFactory.cs b/NzbDrone.Core/Datastore/Migration/Sqlite/MonoSqliteProcessorFactory.cs new file mode 100644 index 000000000..dd8e3740f --- /dev/null +++ b/NzbDrone.Core/Datastore/Migration/Sqlite/MonoSqliteProcessorFactory.cs @@ -0,0 +1,18 @@ +using FluentMigrator; +using FluentMigrator.Runner; +using FluentMigrator.Runner.Generators.SQLite; +using FluentMigrator.Runner.Processors; +using FluentMigrator.Runner.Processors.Sqlite; + +namespace NzbDrone.Core.Datastore.Migration.Sqlite +{ + public class MonoSqliteProcessorFactory : MigrationProcessorFactory + { + public override IMigrationProcessor Create(string connectionString, IAnnouncer announcer, IMigrationProcessorOptions options) + { + var factory = new MonoSqliteDbFactory(); + var connection = factory.CreateConnection(connectionString); + return new SqliteProcessor(connection, new SqliteGenerator(), announcer, options, factory); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Datastore/MigrationHelper.cs b/NzbDrone.Core/Datastore/MigrationHelper.cs deleted file mode 100644 index f1209c891..000000000 --- a/NzbDrone.Core/Datastore/MigrationHelper.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using FluentMigrator; -using FluentMigrator.Runner; -using FluentMigrator.Runner.Initialization; - -namespace NzbDrone.Core.Datastore -{ - public static class MigrationHelper - { - public static void MigrateToLatest(string connectionString, MigrationType migrationType) - { - var announcer = new NlogAnnouncer(); - var assembly = Assembly.GetExecutingAssembly(); - - var migrationContext = new RunnerContext(announcer) - { - Namespace = "NzbDrone.Core.Datastore.Migrations", - ApplicationContext = migrationType - }; - - var options = new MigrationOptions { PreviewOnly = false, Timeout = 60 }; - var factory = new FluentMigrator.Runner.Processors.Sqlite.SqliteProcessorFactory(); - var processor = factory.Create(connectionString, announcer, options); - var runner = new MigrationRunner(assembly, migrationContext, processor); - runner.MigrateUp(true); - } - } - - public class MigrationOptions : IMigrationProcessorOptions - { - public bool PreviewOnly { get; set; } - public int Timeout { get; set; } - } -} diff --git a/NzbDrone.Core/Datastore/TableMapping.cs b/NzbDrone.Core/Datastore/TableMapping.cs new file mode 100644 index 000000000..071ae9854 --- /dev/null +++ b/NzbDrone.Core/Datastore/TableMapping.cs @@ -0,0 +1,71 @@ +using System; +using Marr.Data; +using Marr.Data.Mapping; +using NzbDrone.Core.Configuration; +using NzbDrone.Core.Datastore.Converters; +using NzbDrone.Core.ExternalNotification; +using NzbDrone.Core.Indexers; +using NzbDrone.Core.Instrumentation; +using NzbDrone.Core.Jobs; +using NzbDrone.Core.MediaFiles; +using NzbDrone.Core.Qualities; +using NzbDrone.Core.ReferenceData; +using NzbDrone.Core.RootFolders; +using NzbDrone.Core.Tv; +using BooleanIntConverter = NzbDrone.Core.Datastore.Converters.BooleanIntConverter; + +namespace NzbDrone.Core.Datastore +{ + public static class TableMapping + { + + private static readonly FluentMappings Mapper = new FluentMappings(true); + + public static void Map() + { + RegisterMappers(); + + Mapper.Entity().RegisterModel("Config"); + Mapper.Entity().RegisterModel("RootFolders"); + + Mapper.Entity().RegisterModel("IndexerDefinitions"); + Mapper.Entity().RegisterModel("NewznabDefinitions"); + Mapper.Entity().RegisterModel("JobDefinitions"); + Mapper.Entity().RegisterModel("ExternalNotificationDefinitions"); + + Mapper.Entity().RegisterModel("SceneMappings"); + + Mapper.Entity().RegisterModel("History"); + + Mapper.Entity().RegisterModel("Series"); + Mapper.Entity().RegisterModel("Seasons"); + Mapper.Entity().RegisterModel("Episodes"); + Mapper.Entity().RegisterModel("EpisodeFiles"); + + Mapper.Entity().RegisterModel("QualityProfiles"); + Mapper.Entity().RegisterModel("QualitySizes"); + + Mapper.Entity().RegisterModel("Logs"); + + } + + private static void RegisterMappers() + { + MapRepository.Instance.RegisterTypeConverter(typeof(Int32), new Int32Converter()); + MapRepository.Instance.RegisterTypeConverter(typeof(Boolean), new BooleanIntConverter()); + } + + + private static void RegisterModel(this FluentMappings.MappingsFluentEntity mapBuilder, string tableName) where T : ModelBase + { + mapBuilder.Table.MapTable(tableName) + .Columns + .AutoMapSimpleTypeProperties() + .For(c => c.Id) + .SetPrimaryKey() + .SetReturnValue() + .SetAutoIncrement(); + } + + } +} \ No newline at end of file diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 859071c2a..7263a87ef 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -179,14 +179,6 @@ - - False - ..\packages\System.Data.SQLite.x64.1.0.84.0\lib\net40\System.Data.SQLite.dll - - - False - ..\packages\System.Data.SQLite.x64.1.0.84.0\lib\net40\System.Data.SQLite.Linq.dll - @@ -206,15 +198,21 @@ + + - - - + + + + + + + - +