got basic relationships working

added support for embedded documents.
This commit is contained in:
kay.one
2013-03-25 22:51:56 -07:00
parent b6fc731db8
commit fc641baab3
51 changed files with 359 additions and 127 deletions
@@ -0,0 +1,48 @@
using System;
using Marr.Data.Converters;
using Marr.Data.Mapping;
using Newtonsoft.Json;
namespace NzbDrone.Core.Datastore.Converters
{
public class EmbeddedDocumentConverter : IConverter
{
public object FromDB(ColumnMap map, object dbValue)
{
if (dbValue == DBNull.Value)
{
return DBNull.Value;
}
var stringValue = (string)dbValue;
if (string.IsNullOrWhiteSpace(stringValue))
{
return null;
}
return JsonConvert.DeserializeObject(stringValue, map.FieldType);
}
public object ToDB(object clrValue)
{
if (clrValue == null) return null;
if (clrValue as IEmbeddedDocument == null)
{
throw new InvalidOperationException("Attempted to embedded an object not marked with IEmbeddedDocument");
}
var json = JsonConvert.SerializeObject(clrValue);
return json;
}
public Type DbType
{
get
{
return typeof(string);
}
}
}
}
+3 -2
View File
@@ -1,6 +1,7 @@
using System;
using System.Data;
using System.Data.SQLite;
using Marr.Data;
using Mono.Data.Sqlite;
using NzbDrone.Core.Datastore.Migration.Framework;
@@ -26,7 +27,7 @@ namespace NzbDrone.Core.Datastore
var connectionString = GetConnectionString(dbPath);
_migrationController.MigrateToLatest(connectionString, migrationType);
var dataMapper = new DataMapper(SqliteFactory.Instance, connectionString)
var dataMapper = new DataMapper(SQLiteFactory.Instance, connectionString)
{
SqlMode = SqlModes.Text,
};
@@ -0,0 +1,37 @@
using System;
using Marr.Data.Converters;
using Marr.Data.Mapping;
namespace NzbDrone.Core.Datastore
{
public class EnumIntConverter : IConverter
{
public Type DbType
{
get
{
return typeof(int);
}
}
public object FromDB(ColumnMap map, object dbValue)
{
if (dbValue != null && dbValue != DBNull.Value)
{
return Enum.ToObject(map.FieldType, (Int64)dbValue);
}
return null;
}
public object ToDB(object clrValue)
{
if (clrValue != null)
{
return (int)clrValue;
}
return DBNull.Value;
}
}
}
@@ -0,0 +1,6 @@
namespace NzbDrone.Core.Datastore
{
public interface IEmbeddedDocument
{
}
}
+10
View File
@@ -0,0 +1,10 @@
using System.Collections.Generic;
using Marr.Data;
namespace NzbDrone.Core.Datastore
{
public class LazyList<T> : LazyLoaded<List<T>>
{
}
}
@@ -1,7 +1,7 @@
using System.Reflection;
using FluentMigrator.Runner;
using FluentMigrator.Runner.Initialization;
using NzbDrone.Core.Datastore.Migration.Sqlite;
using FluentMigrator.Runner.Processors.Sqlite;
namespace NzbDrone.Core.Datastore.Migration.Framework
{
@@ -30,7 +30,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
};
var options = new MigrationOptions { PreviewOnly = false, Timeout = 60 };
var factory = new MonoSqliteProcessorFactory();
var factory = new SqliteProcessorFactory();
var processor = factory.Create(connectionString, _announcer, options);
var runner = new MigrationRunner(assembly, migrationContext, processor);
runner.MigrateUp(true);
@@ -1,5 +1,5 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
@@ -28,7 +28,7 @@ namespace NzbDrone.Core.Datastore.Migration
Create.Table("Episodes")
.WithColumn("Id").AsInt32().PrimaryKey().Identity()
.WithColumn("TvdbId").AsInt32().Nullable()
.WithColumn("TvDbEpisodeId").AsInt32().Nullable()
.WithColumn("SeriesId").AsInt32().NotNullable()
.WithColumn("SeasonNumber").AsInt32().NotNullable()
.WithColumn("EpisodeNumber").AsInt32().NotNullable()
@@ -56,8 +56,7 @@ namespace NzbDrone.Core.Datastore.Migration
.WithColumn("SeriesId").AsInt32().NotNullable()
.WithColumn("NzbTitle").AsString().NotNullable()
.WithColumn("Date").AsDateTime().NotNullable()
.WithColumn("Quality").AsInt32().NotNullable()
.WithColumn("Proper").AsBoolean().NotNullable()
.WithColumn("Quality").AsString().NotNullable()
.WithColumn("Indexer").AsString().NotNullable()
.WithColumn("NzbInfoUrl").AsString().Nullable()
.WithColumn("ReleaseGroup").AsString().Nullable();
@@ -131,7 +130,6 @@ namespace NzbDrone.Core.Datastore.Migration
.WithColumn("LastInfoSync").AsDateTime().Nullable()
.WithColumn("LastDiskSync").AsDateTime().Nullable()
.WithColumn("Runtime").AsInt32().NotNullable()
.WithColumn("BannerUrl").AsString().NotNullable()
.WithColumn("SeriesType").AsInt32().NotNullable()
.WithColumn("BacklogSetting").AsInt32().NotNullable()
.WithColumn("Network").AsString().NotNullable()
@@ -140,7 +138,14 @@ namespace NzbDrone.Core.Datastore.Migration
.WithColumn("TvRageId").AsInt32().Nullable()
.WithColumn("TvRageTitle").AsString().NotNullable()
.WithColumn("UtcOffSet").AsInt32().NotNullable()
.WithColumn("FirstAired").AsDateTime().Nullable();
.WithColumn("FirstAired").AsDateTime().Nullable()
.WithColumn("NextAiring").AsDateTime().Nullable();
Create.Table("MediaCovers")
.WithColumn("Id").AsInt32().PrimaryKey().Identity()
.WithColumn("SeriesId").AsInt32().NotNullable()
.WithColumn("Url").AsString().NotNullable()
.WithColumn("CoverType").AsInt32().NotNullable();
}
protected override void LogDbUpgrade()
@@ -1,18 +0,0 @@
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")
{
}
}
}
@@ -1,18 +0,0 @@
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);
}
}
}
+50 -10
View File
@@ -1,4 +1,5 @@
using System;
using System.Reflection;
using Marr.Data;
using Marr.Data.Mapping;
using NzbDrone.Core.Configuration;
@@ -13,6 +14,7 @@ using NzbDrone.Core.ReferenceData;
using NzbDrone.Core.RootFolders;
using NzbDrone.Core.Tv;
using BooleanIntConverter = NzbDrone.Core.Datastore.Converters.BooleanIntConverter;
using System.Linq;
namespace NzbDrone.Core.Datastore
{
@@ -35,12 +37,21 @@ namespace NzbDrone.Core.Datastore
Mapper.Entity<SceneMapping>().RegisterModel("SceneMappings");
Mapper.Entity<History.History>().RegisterModel("History");
Mapper.Entity<History.History>().RegisterModel("History")
.Relationships.AutoMapComplexTypeProperties<ILazyLoaded>()
.For(c => c.Episode)
.LazyLoad((db, history) => db.Query<Episode>().Where(ep => ep.Id == history.Id).ToList());
Mapper.Entity<Series>().RegisterModel("Series")
.Relationships.AutoMapComplexTypeProperties<ILazyLoaded>()
.For(c => c.Covers)
.LazyLoad((db, series) => db.Query<MediaCover.MediaCover>().Where(cover => cover.SeriesId == series.Id).ToList());
Mapper.Entity<Series>().RegisterModel("Series");
Mapper.Entity<Season>().RegisterModel("Seasons");
Mapper.Entity<Episode>().RegisterModel("Episodes");
Mapper.Entity<EpisodeFile>().RegisterModel("EpisodeFiles");
Mapper.Entity<MediaCover.MediaCover>().RegisterModel("MediaCovers");
Mapper.Entity<QualityProfile>().RegisterModel("QualityProfiles");
Mapper.Entity<QualitySize>().RegisterModel("QualitySizes");
@@ -53,19 +64,48 @@ namespace NzbDrone.Core.Datastore
{
MapRepository.Instance.RegisterTypeConverter(typeof(Int32), new Int32Converter());
MapRepository.Instance.RegisterTypeConverter(typeof(Boolean), new BooleanIntConverter());
MapRepository.Instance.RegisterTypeConverter(typeof(Enum), new EnumIntConverter());
MapRepository.Instance.RegisterTypeConverter(typeof(QualityModel), new EmbeddedDocumentConverter());
}
private static void RegisterModel<T>(this FluentMappings.MappingsFluentEntity<T> mapBuilder, string tableName) where T : ModelBase
private static ColumnMapBuilder<T> RegisterModel<T>(this FluentMappings.MappingsFluentEntity<T> mapBuilder, string tableName) where T : ModelBase
{
mapBuilder.Table.MapTable(tableName)
.Columns
.AutoMapSimpleTypeProperties()
.For(c => c.Id)
.SetPrimaryKey()
.SetReturnValue()
.SetAutoIncrement();
return mapBuilder.Table.MapTable(tableName)
.Columns
.AutoMapPropertiesWhere(IsMappableProperty)
.For(c => c.Id)
.SetPrimaryKey()
.SetReturnValue()
.SetAutoIncrement();
}
private static bool IsMappableProperty(MemberInfo memberInfo)
{
var propertyInfo = memberInfo as PropertyInfo;
if (propertyInfo == null) return false;
if (propertyInfo.PropertyType.GetInterfaces().Any(i => i == typeof(IEmbeddedDocument)))
{
return true;
}
return propertyInfo.CanRead && propertyInfo.CanWrite && IsSimpleType(propertyInfo.PropertyType);
}
private static bool IsSimpleType(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
type = type.GetGenericArguments()[0];
}
return type.IsPrimitive
|| type.IsEnum
|| type == typeof(string)
|| type == typeof(DateTime)
|| type == typeof(Decimal);
}
}
}
@@ -1,14 +1,10 @@
using System;
using System.IO;
using System.Linq;
using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.DecisionEngine.Specifications;
using NzbDrone.Core.History;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Model;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.Organizer;
namespace NzbDrone.Core.Download.Clients
@@ -17,21 +17,15 @@ namespace NzbDrone.Core.Download.Clients
private readonly IConfigService _configService;
private readonly HttpProvider _httpProvider;
private readonly DiskProvider _diskProvider;
private readonly UpgradeHistorySpecification _upgradeHistorySpecification;
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public PneumaticProvider(IConfigService configService, HttpProvider httpProvider,
DiskProvider diskProvider, UpgradeHistorySpecification upgradeHistorySpecification)
DiskProvider diskProvider)
{
_configService = configService;
_httpProvider = httpProvider;
_diskProvider = diskProvider;
_upgradeHistorySpecification = upgradeHistorySpecification;
}
public PneumaticProvider()
{
}
public virtual bool DownloadNzb(string url, string title, bool recentlyAired)
@@ -76,7 +70,7 @@ namespace NzbDrone.Core.Download.Clients
public virtual bool IsInQueue(EpisodeParseResult newParseResult)
{
return !_upgradeHistorySpecification.IsSatisfiedBy(newParseResult);
return false;
}
}
}
+4 -2
View File
@@ -1,5 +1,5 @@
using System.Linq;
using System;
using System;
using Marr.Data;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Tv;
@@ -8,6 +8,7 @@ namespace NzbDrone.Core.History
public class History : ModelBase
{
public int EpisodeId { get; set; }
public int SeriesId { get; set; }
public string NzbTitle { get; set; }
public QualityModel Quality { get; set; }
public DateTime Date { get; set; }
@@ -15,5 +16,6 @@ namespace NzbDrone.Core.History
public string NzbInfoUrl { get; set; }
public string ReleaseGroup { get; set; }
public LazyLoaded<Episode> Episode { get; set; }
}
}
+3 -1
View File
@@ -1,4 +1,5 @@
using System.Linq;
using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.MediaCover
{
@@ -10,9 +11,10 @@ namespace NzbDrone.Core.MediaCover
Fanart = 2
}
public class MediaCover
public class MediaCover : ModelBase
{
public MediaCoverTypes CoverType { get; set; }
public string Url { get; set; }
public int SeriesId { get; set; }
}
}
@@ -37,7 +37,7 @@ namespace NzbDrone.Core.MediaCover
private void EnsureCovers(Series series)
{
foreach (var cover in series.Covers)
foreach (var cover in series.Covers.Value)
{
var fileName = GetCoverPath(series.Id, cover.CoverType);
if (!_diskProvider.FileExists(fileName))
+5 -5
View File
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using NLog;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.MediaCover;
using NzbDrone.Core.Tv;
using NzbDrone.Common;
@@ -55,7 +56,7 @@ namespace NzbDrone.Core.MetadataSource
series.Title = tvDbSeries.SeriesName;
series.AirTime = CleanAirsTime(tvDbSeries.Airs_Time);
series.Overview = tvDbSeries.Overview;
series.Status = tvDbSeries.Status == "Continuing" ? SeriesStatusType.Continuing : SeriesStatusType.Ended ;
series.Status = tvDbSeries.Status == "Continuing" ? SeriesStatusType.Continuing : SeriesStatusType.Ended;
series.Language = tvDbSeries.Language ?? string.Empty;
series.CleanTitle = Parser.NormalizeTitle(tvDbSeries.SeriesName);
series.LastInfoSync = DateTime.Now;
@@ -65,21 +66,20 @@ namespace NzbDrone.Core.MetadataSource
series.Runtime = Convert.ToInt32(tvDbSeries.Runtime);
}
series.Covers = new List<MediaCover.MediaCover>();
if (!string.IsNullOrWhiteSpace(tvDbSeries.banner))
{
series.Covers.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Banner, Url = tvDbSeries.banner });
series.Covers.Value.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Banner, Url = tvDbSeries.banner, SeriesId = series.Id });
}
if (!string.IsNullOrWhiteSpace(tvDbSeries.fanart))
{
series.Covers.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Fanart, Url = tvDbSeries.fanart });
series.Covers.Value.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Fanart, Url = tvDbSeries.fanart, SeriesId = series.Id });
}
if (!string.IsNullOrWhiteSpace(tvDbSeries.poster))
{
series.Covers.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Poster, Url = tvDbSeries.poster });
series.Covers.Value.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Poster, Url = tvDbSeries.poster, SeriesId = series.Id });
}
series.Network = tvDbSeries.Network;
+12 -6
View File
@@ -152,10 +152,6 @@
<HintPath>..\packages\MediaInfoNet.0.3\lib\MediaInfoDotNet.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Mono.Data.Sqlite, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Libraries\Sqlite\Mono.Data.Sqlite.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
@@ -179,6 +175,14 @@
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Data.SQLite, Version=1.0.84.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\System.Data.SQLite.1.0.84.0\lib\net40\System.Data.SQLite.dll</HintPath>
</Reference>
<Reference Include="System.Data.SQLite.Linq, Version=1.0.84.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\System.Data.SQLite.1.0.84.0\lib\net40\System.Data.SQLite.Linq.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Web" />
@@ -200,16 +204,18 @@
<Compile Include="ContainerExtensions.cs" />
<Compile Include="Datastore\Converters\BooleanIntConverter.cs" />
<Compile Include="Datastore\Converters\Int32Converter.cs" />
<Compile Include="Datastore\Converters\EmbeddedDocumentConverter.cs" />
<Compile Include="Datastore\Database.cs" />
<Compile Include="Datastore\DbFactory.cs" />
<Compile Include="Datastore\EnumIntConverter.cs" />
<Compile Include="Datastore\IEmbeddedDocument.cs" />
<Compile Include="Datastore\LazyList.cs" />
<Compile Include="Datastore\Migration\Framework\MigrationController.cs" />
<Compile Include="Datastore\Migration\Framework\MigrationOptions.cs" />
<Compile Include="Datastore\Migration\Framework\NlogAnnouncer.cs" />
<Compile Include="Datastore\Migration\Migration20130324.cs" />
<Compile Include="Datastore\Migration\Framework\NzbDroneMigrationBase.cs" />
<Compile Include="Datastore\MigrationType.cs" />
<Compile Include="Datastore\Migration\Sqlite\MonoSqliteDbFactory.cs" />
<Compile Include="Datastore\Migration\Sqlite\MonoSqliteProcessorFactory.cs" />
<Compile Include="Datastore\ModelBase.cs" />
<Compile Include="Datastore\BasicRepository.cs" />
<Compile Include="Datastore\TableMapping.cs" />
+2 -1
View File
@@ -1,10 +1,11 @@
using System.Linq;
using System;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Qualities;
namespace NzbDrone.Core.Tv
{
public class QualityModel : IComparable<QualityModel>
public class QualityModel : IComparable<QualityModel>, IEmbeddedDocument
{
public Quality Quality { get; set; }
+7 -6
View File
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System;
using System;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Model;
using NzbDrone.Core.Qualities;
@@ -16,6 +15,11 @@ namespace NzbDrone.Core.Tv
public class Series : ModelBase
{
public Series()
{
Covers = new LazyList<MediaCover.MediaCover>();
}
public int TvDbId { get; set; }
public string Title { get; set; }
public string CleanTitle { get; set; }
@@ -30,7 +34,7 @@ namespace NzbDrone.Core.Tv
public DateTime? LastInfoSync { get; set; }
public DateTime? LastDiskSync { get; set; }
public int Runtime { get; set; }
public List<MediaCover.MediaCover> Covers { get; set; }
public LazyList<MediaCover.MediaCover> Covers { get; set; }
public SeriesTypes SeriesType { get; set; }
public BacklogSettingType BacklogSetting { get; set; }
public string Network { get; set; }
@@ -44,9 +48,6 @@ namespace NzbDrone.Core.Tv
public DateTime? FirstAired { get; set; }
public QualityProfile QualityProfile { get; set; }
public int EpisodeCount { get; set; }
public int EpisodeFileCount { get; set; }
public int SeasonCount { get; set; }
public DateTime? NextAiring { get; set; }
}
}
+1 -1
View File
@@ -13,6 +13,6 @@
<package id="RestSharp" version="104.1" targetFramework="net40" />
<package id="SignalR.Hosting.Common" version="0.5.3" targetFramework="net40" />
<package id="SignalR.Server" version="0.5.3" targetFramework="net40" />
<package id="System.Data.SQLite.x86" version="1.0.84.0" targetFramework="net40" />
<package id="System.Data.SQLite" version="1.0.84.0" targetFramework="net40" />
<package id="twitterizer" version="2.4.0.26532" />
</packages>