Migrator.net fails

This commit is contained in:
kay.one 2011-05-23 16:29:14 -07:00
parent fad0c6265c
commit 180da4c82a
19 changed files with 592 additions and 40 deletions

View File

@ -8,4 +8,12 @@
type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
</DbProviderFactories>
</system.data>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.0.66.0" newVersion="1.0.66.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -59,6 +59,18 @@
<Reference Include="Microsoft.Practices.Unity.Interception.Configuration">
<HintPath>..\packages\Unity.2.0\lib\20\Microsoft.Practices.Unity.Interception.Configuration.dll</HintPath>
</Reference>
<Reference Include="Migrator, Version=0.9.0.28138, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MigratorDotNet.0.9.0.28138\lib\Net40\Migrator.dll</HintPath>
</Reference>
<Reference Include="Migrator.Framework, Version=0.9.0.26940, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MigratorDotNet.0.9.0.28138\lib\Net40\Migrator.Framework.dll</HintPath>
</Reference>
<Reference Include="Migrator.Providers, Version=0.9.0.26941, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MigratorDotNet.0.9.0.28138\lib\Net40\Migrator.Providers.dll</HintPath>
</Reference>
<Reference Include="Moq, Version=4.0.10827.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
</Reference>
@ -100,6 +112,7 @@
<Compile Include="Framework\ExceptionVerification.cs" />
<Compile Include="Framework\TestBase.cs" />
<Compile Include="JobProviderTest.cs" />
<Compile Include="RepositoryProviderTest.cs" />
<Compile Include="RootDirProviderTest.cs" />
<Compile Include="IndexerProviderTest.cs" />
<Compile Include="HistoryProviderTest.cs" />

View File

@ -0,0 +1,172 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using Gallio.Framework;
using MbUnit.Framework;
using MbUnit.Framework.ContractVerifiers;
using Migrator.Framework;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Instrumentation;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework;
using SubSonic.DataProviders;
using SubSonic.Repository;
using SubSonic.Schema;
using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Test
{
[TestFixture]
// ReSharper disable InconsistentNaming
public class RepositoryProviderTest
{
[Test]
public void Get_Assembly_repos()
{
var provider = new RepositoryProvider();
var types = provider.GetRepositoryTypes();
Assert.IsNotEmpty(types);
Assert.Contains(types, typeof(Config));
Assert.Contains(types, typeof(Episode));
Assert.Contains(types, typeof(EpisodeFile));
Assert.Contains(types, typeof(ExternalNotificationSetting));
Assert.Contains(types, typeof(History));
Assert.Contains(types, typeof(IndexerSetting));
Assert.Contains(types, typeof(JobSetting));
Assert.Contains(types, typeof(RootDir));
Assert.Contains(types, typeof(Season));
Assert.Contains(types, typeof(Series));
Assert.Contains(types, typeof(QualityProfile));
Assert.DoesNotContain(types, typeof(QualityTypes));
}
[Test]
public void Get_table_columns()
{
var provider = new RepositoryProvider();
var typeTable = provider.GetSchemaFromType(typeof(TestRepoType));
Assert.IsNotNull(typeTable.Columns);
Assert.Count(3, typeTable.Columns);
Assert.AreEqual("TestRepoTypes", typeTable.Name);
}
[Test]
public void ConvertToMigratorColumn()
{
var provider = new RepositoryProvider();
var subsonicColumn = new DatabaseColumn
{
Name = "Name",
DataType = DbType.Boolean,
IsPrimaryKey = true,
IsNullable = true
};
var migColumn = provider.ConvertToMigratorColumn(subsonicColumn);
Assert.IsTrue(migColumn.IsPrimaryKey);
Assert.AreEqual(ColumnProperty.Null | ColumnProperty.PrimaryKey, migColumn.ColumnProperty);
}
[Test]
public void GetDbColumns()
{
string connectionString = "Data Source=" + Guid.NewGuid() + ".db;Version=3;New=True";
var dbProvider = ProviderFactory.GetProvider(connectionString, "System.Data.SQLite");
var repo = new SimpleRepository(dbProvider, SimpleRepositoryOptions.RunMigrations);
repo.Add(new TestRepoType(){Value = "Dummy"});
var repositoryProvider = new RepositoryProvider();
var columns = repositoryProvider.GetColumnsFromDatabase(connectionString, "TestRepoTypes");
Assert.Count(3, columns);
}
[Test]
public void DeleteColumns()
{
string connectionString = "Data Source=" + Guid.NewGuid() + ".db;Version=3;New=True";
var dbProvider = ProviderFactory.GetProvider(connectionString, "System.Data.SQLite");
var repo = new SimpleRepository(dbProvider, SimpleRepositoryOptions.RunMigrations);
repo.Add(new TestRepoType(){Value = "Dummy"});
var repositoryProvider = new RepositoryProvider();
var typeSchema = repositoryProvider.GetSchemaFromType(typeof(TestRepoType2));
var columns = repositoryProvider.GetColumnsFromDatabase(connectionString, "TestRepoTypes");
var deletedColumns = repositoryProvider.GetDeletedColumns(typeSchema, columns);
Assert.Count(1, deletedColumns);
Assert.AreEqual("NewName", deletedColumns[0].Name.Trim('[', ']'));
}
[Test]
public void NewColumns()
{
string connectionString = "Data Source=" + Guid.NewGuid() + ".db;Version=3;New=True";
var dbProvider = ProviderFactory.GetProvider(connectionString, "System.Data.SQLite");
var repo = new SimpleRepository(dbProvider, SimpleRepositoryOptions.RunMigrations);
repo.Add(new TestRepoType2() { Value = "dummy" });
var repositoryProvider = new RepositoryProvider();
var typeSchema = repositoryProvider.GetSchemaFromType(typeof(TestRepoType));
var columns = repositoryProvider.GetColumnsFromDatabase(connectionString, "TestRepoType2s");
var deletedColumns = repositoryProvider.GetNewColumns(typeSchema, columns);
Assert.Count(1, deletedColumns);
Assert.AreEqual("NewName", deletedColumns[0].Name.Trim('[', ']'));
}
}
public class TestRepoType
{
[SubSonicPrimaryKey]
public int TestId { get; set; }
[SubSonicColumnNameOverride("NewName")]
public Boolean BaddBoolean { get; set; }
public string Value { get; set; }
[SubSonicIgnore]
public Boolean BaddBooleanIgnored { get; set; }
}
public class TestRepoType2
{
[SubSonicPrimaryKey]
public int TestId { get; set; }
public string Value { get; set; }
[SubSonicIgnore]
public Boolean BaddBooleanIgnored { get; set; }
}
}

View File

@ -6,6 +6,7 @@ using System.IO;
using System.Web.Hosting;
using Ninject;
using NLog;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Instrumentation;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
@ -43,12 +44,28 @@ namespace NzbDrone.Core
{
if (_kernel == null)
{
BindKernel();
InitializeApp();
}
return _kernel;
}
}
private static void InitializeApp()
{
BindKernel();
LogConfiguration.Setup();
Migrations.Run();
ForceMigration(_kernel.Get<IRepository>());
SetupDefaultQualityProfiles(_kernel.Get<IRepository>()); //Setup the default QualityProfiles on start-up
BindIndexers();
BindJobs();
BindExternalNotifications();
}
public static void BindKernel()
{
lock (KernelLock)
@ -56,27 +73,7 @@ namespace NzbDrone.Core
Logger.Debug("Binding Ninject's Kernel");
_kernel = new StandardKernel();
//Sqlite
var appDataPath = new DirectoryInfo(Path.Combine(AppPath, "App_Data"));
if (!appDataPath.Exists) appDataPath.Create();
string connectionString = String.Format("Data Source={0};Version=3;",
Path.Combine(appDataPath.FullName, "nzbdrone.db"));
var dbProvider = ProviderFactory.GetProvider(connectionString, "System.Data.SQLite");
string logConnectionString = String.Format("Data Source={0};Version=3;",
Path.Combine(appDataPath.FullName, "log.db"));
var logDbProvider = ProviderFactory.GetProvider(logConnectionString, "System.Data.SQLite");
//SQLExpress
//string logConnectionString = String.Format(@"server=.\SQLExpress; database=NzbDroneLogs; Trusted_Connection=True;");
//var logDbProvider = ProviderFactory.GetProvider(logConnectionString, "System.Data.SqlClient");
var logRepository = new SimpleRepository(logDbProvider, SimpleRepositoryOptions.RunMigrations);
//dbProvider.ExecuteQuery(new QueryCommand("VACUUM", dbProvider));
//dbProvider.Log = new NlogWriter();
_kernel.Bind<QualityProvider>().ToSelf().InSingletonScope();
_kernel.Bind<TvDbProvider>().ToSelf().InTransientScope();
_kernel.Bind<HttpProvider>().ToSelf().InSingletonScope();
@ -100,21 +97,10 @@ namespace NzbDrone.Core
_kernel.Bind<IndexerProvider>().ToSelf().InSingletonScope();
_kernel.Bind<WebTimer>().ToSelf().InSingletonScope();
_kernel.Bind<AutoConfigureProvider>().ToSelf().InSingletonScope();
_kernel.Bind<IRepository>().ToMethod(
c => new SimpleRepository(dbProvider, SimpleRepositoryOptions.RunMigrations)).InSingletonScope();
_kernel.Bind<IRepository>().ToConstant(logRepository).WhenInjectedInto<SubsonicTarget>().
InSingletonScope();
_kernel.Bind<IRepository>().ToConstant(logRepository).WhenInjectedInto<LogProvider>().InSingletonScope();
LogConfiguration.Setup();
ForceMigration(_kernel.Get<IRepository>());
SetupDefaultQualityProfiles(_kernel.Get<IRepository>()); //Setup the default QualityProfiles on start-up
BindIndexers();
BindJobs();
BindExternalNotifications();
_kernel.Bind<IRepository>().ToConstant(Connection.MainDataRepository).InSingletonScope();
_kernel.Bind<IRepository>().ToConstant(Connection.LogDataRepository).WhenInjectedInto<SubsonicTarget>().InSingletonScope();
_kernel.Bind<IRepository>().ToConstant(Connection.LogDataRepository).WhenInjectedInto<LogProvider>().InSingletonScope();
}
}

View File

@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using SubSonic.DataProviders;
using SubSonic.Repository;
namespace NzbDrone.Core.Datastore
{
public static class Connection
{
private static readonly DirectoryInfo AppDataPath = new DirectoryInfo(Path.Combine(CentralDispatch.AppPath, "App_Data"));
static Connection()
{
if (!AppDataPath.Exists) AppDataPath.Create();
}
public static String MainConnectionString
{
get
{
return String.Format("Data Source={0};Version=3;", Path.Combine(AppDataPath.FullName, "nzbdrone.db"));
}
}
public static String LogConnectionString
{
get
{
return String.Format("Data Source={0};Version=3;", Path.Combine(AppDataPath.FullName, "log.db"));
}
}
private static IDataProvider _mainDataProvider;
public static IDataProvider MainDataProvider
{
get
{
if (_mainDataProvider == null)
{
_mainDataProvider = ProviderFactory.GetProvider(Connection.MainConnectionString, "System.Data.SQLite");
}
return _mainDataProvider;
}
}
private static IDataProvider _logDataProvider;
public static IDataProvider LogDataProvider
{
get
{
if (_logDataProvider == null)
{
_logDataProvider = ProviderFactory.GetProvider(Connection.LogConnectionString, "System.Data.SQLite");
}
return _logDataProvider;
}
}
private static SimpleRepository _mainDataRepository;
public static SimpleRepository MainDataRepository
{
get
{
if (_mainDataRepository == null)
{
_mainDataRepository = new SimpleRepository(MainDataProvider, SimpleRepositoryOptions.RunMigrations);
}
return _mainDataRepository;
}
}
private static SimpleRepository _logDataRepository;
public static SimpleRepository LogDataRepository
{
get
{
if (_logDataRepository == null)
{
_logDataRepository = new SimpleRepository(LogDataProvider, SimpleRepositoryOptions.RunMigrations);
}
return _logDataRepository;
}
}
}
}

View File

@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using Migrator.Framework;
using NLog;
namespace NzbDrone.Core.Datastore
{
class MigrationLogger : ILogger
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public void Started(List<long> currentVersion, long finalVersion)
{
Logger.Info("Starting Datastore migration {0} -> {1}", String.Join(",", currentVersion), finalVersion);
}
public void MigrateUp(long version, string migrationName)
{
Logger.Info("Starting MigrateUp {0} [{1}]", version, migrationName);
}
public void MigrateDown(long version, string migrationName)
{
Logger.Info("Starting MigrateDown {0} [{1}]", version, migrationName);
}
public void Skipping(long version)
{
Logger.Info("Skipping MigrateDown {0}", version);
}
public void RollingBack(long originalVersion)
{
Logger.Info("Rolling Back to {0}", originalVersion);
}
public void ApplyingDBChange(string sql)
{
Logger.Info("Applying DB Change {0}", sql);
}
public void Exception(long version, string migrationName, Exception ex)
{
Logger.ErrorException(migrationName + " " + version, ex);
}
public void Exception(string message, Exception ex)
{
Logger.ErrorException(message, ex);
}
public void Finished(List<long> currentVersion, long finalVersion)
{
Logger.Info("Finished Datastore migration {0} -> {1}", String.Join(",", currentVersion), finalVersion);
}
public void Log(string format, params object[] args)
{
Logger.Info(format, args);
}
public void Warn(string format, params object[] args)
{
Logger.Warn(format, args);
}
public void Trace(string format, params object[] args)
{
Logger.Trace(format, args);
}
}
}

View File

@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using Migrator.Framework;
using NLog;
using SubSonic.Extensions;
using SubSonic.Schema;
namespace NzbDrone.Core.Datastore
{
public class Migrations
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public static void Run()
{
Logger.Info("Preparing to migrate databse");
try
{
var mig = new Migrator.Migrator("Sqlite", Connection.MainConnectionString,
Assembly.GetAssembly(typeof(Migrations)), true, new MigrationLogger());
mig.MigrateToLastVersion();
Logger.Info("Database migration completed");
}
catch (Exception e)
{
Logger.FatalException("An error has occured while migrating database", e);
}
}
public static void RemoveDeletedColumns(ITransformationProvider transformationProvider)
{
var provider = new RepositoryProvider();
var repoTypes = provider.GetRepositoryTypes();
foreach (var repoType in repoTypes)
{
var typeSchema = provider.GetSchemaFromType(repoType);
var dbColumns = provider.GetColumnsFromDatabase(Connection.MainConnectionString, typeSchema.Name);
var deletedColumns = provider.GetDeletedColumns(typeSchema, dbColumns);
foreach (var deletedColumn in deletedColumns)
{
Logger.Info("Removing column '{0}' from '{1}'", deletedColumn.Name, repoType.Name);
transformationProvider.RemoveColumn(typeSchema.Name, deletedColumn.Name);
}
}
}
public static void AddNewColumns(ITransformationProvider transformationProvider)
{
var provider = new RepositoryProvider();
var repoTypes = provider.GetRepositoryTypes();
foreach (var repoType in repoTypes)
{
var typeSchema = provider.GetSchemaFromType(repoType);
var dbColumns = provider.GetColumnsFromDatabase(Connection.MainConnectionString, typeSchema.Name);
var newColumns = provider.GetNewColumns(typeSchema, dbColumns);
foreach (var newColumn in newColumns)
{
Logger.Info("Adding column '{0}' to '{1}'", newColumn.Name, repoType.Name);
transformationProvider.AddColumn(typeSchema.Name, newColumn);
}
}
}
}
[Migration(20110523)]
public class Migration20110523 : Migration
{
public override void Up()
{
Migrations.RemoveDeletedColumns(Database);
Migrations.AddNewColumns(Database);
}
public override void Down()
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using Migrator.Providers;
using Migrator.Providers.SQLite;
using SubSonic.DataProviders;
using SubSonic.Extensions;
using SubSonic.Schema;
using Migrator.Framework;
namespace NzbDrone.Core.Datastore
{
public class RepositoryProvider
{
public virtual IList<Type> GetRepositoryTypes()
{
var coreAssembly = Assembly.GetExecutingAssembly();
var repoTypes = coreAssembly.GetTypes().Where(t => !String.IsNullOrWhiteSpace(t.Namespace) && t.Namespace.StartsWith("NzbDrone.Core.Repository"));
repoTypes = repoTypes.Where(r => !r.IsEnum);
return repoTypes.ToList();
}
public virtual ITable GetSchemaFromType(Type type)
{
return type.ToSchemaTable(Connection.MainDataProvider);
}
public virtual Column[] GetColumnsFromDatabase(string connectionString, string tableName)
{
var dialact = new SQLiteDialect();
var mig = new SQLiteTransformationProvider(dialact, connectionString);
return mig.GetColumns(tableName);
}
public virtual List<Column> GetDeletedColumns(ITable typeSchema, Column[] dbColumns)
{
var deleteColumns = new List<Column>();
foreach (var dbColumn in dbColumns)
{
if (!typeSchema.Columns.ToList().Exists(c => c.Name == dbColumn.Name.Trim('[', ']')))
{
deleteColumns.Add(dbColumn);
}
}
return deleteColumns;
}
public virtual List<Column> GetNewColumns(ITable typeSchema, Column[] dbColumns)
{
var newColumns = new List<Column>();
foreach (var typeColumn in typeSchema.Columns)
{
if (!dbColumns.ToList().Exists(c => c.Name.Trim('[', ']') == typeColumn.Name))
{
newColumns.Add(ConvertToMigratorColumn(typeColumn));
}
}
return newColumns;
}
public virtual Column ConvertToMigratorColumn(SubSonic.Schema.IColumn subsonicColumns)
{
var migColumn = new Column(subsonicColumns.Name, subsonicColumns.DataType);
if (subsonicColumns.IsPrimaryKey)
{
migColumn.ColumnProperty = ColumnProperty.PrimaryKey;
}
if (subsonicColumns.IsNullable)
{
migColumn.ColumnProperty = migColumn.ColumnProperty | ColumnProperty.Null;
}
else
{
migColumn.ColumnProperty = migColumn.ColumnProperty | ColumnProperty.NotNull;
migColumn.DefaultValue = false;
}
return migColumn;
}
}
}

View File

@ -128,13 +128,16 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>Libraries\Exceptioneer.WindowsFormsClient.dll</HintPath>
</Reference>
<Reference Include="Migrator">
<Reference Include="Migrator, Version=0.9.0.28138, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MigratorDotNet.0.9.0.28138\lib\Net40\Migrator.dll</HintPath>
</Reference>
<Reference Include="Migrator.Framework">
<Reference Include="Migrator.Framework, Version=0.9.0.26940, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MigratorDotNet.0.9.0.28138\lib\Net40\Migrator.Framework.dll</HintPath>
</Reference>
<Reference Include="Migrator.Providers">
<Reference Include="Migrator.Providers, Version=0.9.0.26941, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MigratorDotNet.0.9.0.28138\lib\Net40\Migrator.Providers.dll</HintPath>
</Reference>
<Reference Include="Ninject, Version=2.2.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL">
@ -162,6 +165,10 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Datastore\Connection.cs" />
<Compile Include="Datastore\MigrationLogger.cs" />
<Compile Include="Datastore\Migrations.cs" />
<Compile Include="Datastore\RepositoryProvider.cs" />
<Compile Include="Helpers\EpisodeRenameHelper.cs" />
<Compile Include="Helpers\EpisodeSortingHelper.cs" />
<Compile Include="Helpers\SceneNameHelper.cs" />
@ -269,7 +276,6 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<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

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Ninject" version="2.2.1.0" />
<package id="MigratorDotNet" version="0.9.0.28138" />
</packages>

View File

@ -61,6 +61,12 @@
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.0.66.0" newVersion="1.0.66.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.data>
<DbProviderFactories>