From a1d7f2d8b3beeca183673a725342d25a98ab4382 Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 19 Jun 2015 12:03:02 +0200 Subject: [PATCH] Created IMigrationEntryService and affiliated models, etc.... also updates the IServerRegistration stuff to be interfaced. --- src/Umbraco.Core/Models/IMigrationEntry.cs | 11 ++ .../Models/IServerRegistration.cs | 31 +++++ src/Umbraco.Core/Models/MigrationEntry.cs | 52 ++++++++ src/Umbraco.Core/Models/Rdbms/MigrationDto.cs | 29 +++++ src/Umbraco.Core/Models/ServerRegistration.cs | 2 +- .../Factories/MigrationEntryFactory.cs | 33 +++++ .../Factories/ServerRegistrationFactory.cs | 20 ++- .../Mappers/MigrationEntryMapper.cs | 38 ++++++ .../Mappers/ServerRegistrationMapper.cs | 1 + .../Interfaces/IMigrationEntryRepository.cs | 9 ++ .../IServerRegistrationRepository.cs | 10 ++ .../Repositories/MigrationEntryRepository.cs | 116 ++++++++++++++++++ .../ServerRegistrationRepository.cs | 50 +++----- .../Persistence/RepositoryFactory.cs | 10 +- .../Services/IMigrationEntryService.cs | 32 +++++ .../Services/IServerRegistrationService.cs | 35 ++++++ .../Services/MigrationEntryService.cs | 80 ++++++++++++ .../Services/ServerRegistrationService.cs | 13 +- src/Umbraco.Core/Services/ServiceContext.cs | 24 +++- src/Umbraco.Core/Umbraco.Core.csproj | 12 ++ .../ServerRegistrationRepositoryTest.cs | 4 +- 21 files changed, 555 insertions(+), 57 deletions(-) create mode 100644 src/Umbraco.Core/Models/IMigrationEntry.cs create mode 100644 src/Umbraco.Core/Models/IServerRegistration.cs create mode 100644 src/Umbraco.Core/Models/MigrationEntry.cs create mode 100644 src/Umbraco.Core/Models/Rdbms/MigrationDto.cs create mode 100644 src/Umbraco.Core/Persistence/Factories/MigrationEntryFactory.cs create mode 100644 src/Umbraco.Core/Persistence/Mappers/MigrationEntryMapper.cs create mode 100644 src/Umbraco.Core/Persistence/Repositories/Interfaces/IMigrationEntryRepository.cs create mode 100644 src/Umbraco.Core/Persistence/Repositories/Interfaces/IServerRegistrationRepository.cs create mode 100644 src/Umbraco.Core/Persistence/Repositories/MigrationEntryRepository.cs create mode 100644 src/Umbraco.Core/Services/IMigrationEntryService.cs create mode 100644 src/Umbraco.Core/Services/IServerRegistrationService.cs create mode 100644 src/Umbraco.Core/Services/MigrationEntryService.cs diff --git a/src/Umbraco.Core/Models/IMigrationEntry.cs b/src/Umbraco.Core/Models/IMigrationEntry.cs new file mode 100644 index 0000000000..0eb45394c4 --- /dev/null +++ b/src/Umbraco.Core/Models/IMigrationEntry.cs @@ -0,0 +1,11 @@ +using System; +using Umbraco.Core.Models.EntityBase; + +namespace Umbraco.Core.Models +{ + public interface IMigrationEntry : IAggregateRoot, IRememberBeingDirty + { + string MigrationName { get; set; } + Version Version { get; set; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/IServerRegistration.cs b/src/Umbraco.Core/Models/IServerRegistration.cs new file mode 100644 index 0000000000..9eb6815bbe --- /dev/null +++ b/src/Umbraco.Core/Models/IServerRegistration.cs @@ -0,0 +1,31 @@ +using System; +using Umbraco.Core.Models.EntityBase; +using Umbraco.Core.Sync; + +namespace Umbraco.Core.Models +{ + public interface IServerRegistration : IServerAddress, IAggregateRoot, IRememberBeingDirty + { + /// + /// Gets or sets the server unique identity. + /// + string ServerIdentity { get; set; } + + new string ServerAddress { get; set; } + + /// + /// Gets or sets a value indicating whether the server is active. + /// + bool IsActive { get; set; } + + /// + /// Gets the date and time the registration was created. + /// + DateTime Registered { get; set; } + + /// + /// Gets the date and time the registration was last accessed. + /// + DateTime Accessed { get; set; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/MigrationEntry.cs b/src/Umbraco.Core/Models/MigrationEntry.cs new file mode 100644 index 0000000000..fa41346b86 --- /dev/null +++ b/src/Umbraco.Core/Models/MigrationEntry.cs @@ -0,0 +1,52 @@ +using System; +using System.Reflection; +using Umbraco.Core.Models.EntityBase; + +namespace Umbraco.Core.Models +{ + public class MigrationEntry : Entity, IMigrationEntry + { + public MigrationEntry() + { + } + + public MigrationEntry(int id, DateTime createDate, string migrationName, Version version) + { + Id = id; + CreateDate = createDate; + _migrationName = migrationName; + _version = version; + } + + private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.MigrationName); + private static readonly PropertyInfo VersionSelector = ExpressionHelper.GetPropertyInfo(x => x.Version); + private string _migrationName; + private Version _version; + + public string MigrationName + { + get { return _migrationName; } + set + { + SetPropertyValueAndDetectChanges(o => + { + _migrationName = value; + return _migrationName; + }, _migrationName, NameSelector); + } + } + + public Version Version + { + get { return _version; } + set + { + SetPropertyValueAndDetectChanges(o => + { + _version = value; + return _version; + }, _version, VersionSelector); + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/MigrationDto.cs b/src/Umbraco.Core/Models/Rdbms/MigrationDto.cs new file mode 100644 index 0000000000..ffd000278d --- /dev/null +++ b/src/Umbraco.Core/Models/Rdbms/MigrationDto.cs @@ -0,0 +1,29 @@ +using System; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.DatabaseAnnotations; + +namespace Umbraco.Core.Models.Rdbms +{ + [TableName("umbracoMigration")] + [PrimaryKey("id")] + [ExplicitColumns] + internal class MigrationDto + { + [Column("id")] + [PrimaryKeyColumn(AutoIncrement = true)] + public int Id { get; set; } + + [Column("name")] + [Length(255)] + [Index(IndexTypes.UniqueNonClustered, ForColumns = "name,version", Name = "IX_umbracoMigration")] + public string Name { get; set; } + + [Column("createDate")] + [Constraint(Default = "getdate()")] + public DateTime CreateDate { get; set; } + + [Column("version")] + [Length(50)] + public string Version { get; set; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/ServerRegistration.cs b/src/Umbraco.Core/Models/ServerRegistration.cs index 900d6deb94..9a871859b6 100644 --- a/src/Umbraco.Core/Models/ServerRegistration.cs +++ b/src/Umbraco.Core/Models/ServerRegistration.cs @@ -9,7 +9,7 @@ namespace Umbraco.Core.Models /// /// Represents a registered server in a multiple-servers environment. /// - public class ServerRegistration : Entity, IServerAddress, IAggregateRoot + public class ServerRegistration : Entity, IServerRegistration { private string _serverAddress; private string _serverIdentity; diff --git a/src/Umbraco.Core/Persistence/Factories/MigrationEntryFactory.cs b/src/Umbraco.Core/Persistence/Factories/MigrationEntryFactory.cs new file mode 100644 index 0000000000..01feb74eaa --- /dev/null +++ b/src/Umbraco.Core/Persistence/Factories/MigrationEntryFactory.cs @@ -0,0 +1,33 @@ +using System; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Rdbms; + +namespace Umbraco.Core.Persistence.Factories +{ + internal class MigrationEntryFactory + { + public MigrationEntry BuildEntity(MigrationDto dto) + { + var model = new MigrationEntry(dto.Id, dto.CreateDate, dto.Name, Version.Parse(dto.Version)); + //on initial construction we don't want to have dirty properties tracked + // http://issues.umbraco.org/issue/U4-1946 + model.ResetDirtyProperties(false); + return model; + } + + public MigrationDto BuildDto(IMigrationEntry entity) + { + var dto = new MigrationDto + { + CreateDate = entity.CreateDate, + Name = entity.MigrationName, + Version = entity.Version.ToString() + }; + + if (entity.HasIdentity) + dto.Id = entity.Id; + + return dto; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Factories/ServerRegistrationFactory.cs b/src/Umbraco.Core/Persistence/Factories/ServerRegistrationFactory.cs index aa0ed25ccd..9ecc02e213 100644 --- a/src/Umbraco.Core/Persistence/Factories/ServerRegistrationFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/ServerRegistrationFactory.cs @@ -5,8 +5,6 @@ namespace Umbraco.Core.Persistence.Factories { internal class ServerRegistrationFactory { - #region Implementation of IEntityFactory - public ServerRegistration BuildEntity(ServerRegistrationDto dto) { var model = new ServerRegistration(dto.Id, dto.ServerAddress, dto.ServerIdentity, dto.DateRegistered, dto.DateAccessed, dto.IsActive); @@ -16,23 +14,21 @@ namespace Umbraco.Core.Persistence.Factories return model; } - public ServerRegistrationDto BuildDto(ServerRegistration entity) + public ServerRegistrationDto BuildDto(IServerRegistration entity) { var dto = new ServerRegistrationDto - { - ServerAddress = entity.ServerAddress, - DateRegistered = entity.CreateDate, - IsActive = entity.IsActive, - DateAccessed = entity.UpdateDate, - ServerIdentity = entity.ServerIdentity - }; + { + ServerAddress = entity.ServerAddress, + DateRegistered = entity.CreateDate, + IsActive = entity.IsActive, + DateAccessed = entity.UpdateDate, + ServerIdentity = entity.ServerIdentity + }; if (entity.HasIdentity) dto.Id = entity.Id; return dto; } - - #endregion } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Mappers/MigrationEntryMapper.cs b/src/Umbraco.Core/Persistence/Mappers/MigrationEntryMapper.cs new file mode 100644 index 0000000000..5c0838ede9 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Mappers/MigrationEntryMapper.cs @@ -0,0 +1,38 @@ +using System.Collections.Concurrent; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Rdbms; + +namespace Umbraco.Core.Persistence.Mappers +{ + [MapperFor(typeof(MigrationEntry))] + [MapperFor(typeof(IMigrationEntry))] + internal sealed class MigrationEntryMapper : BaseMapper + { + private static readonly ConcurrentDictionary PropertyInfoCacheInstance = new ConcurrentDictionary(); + + //NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it + // otherwise that would fail because there is no public constructor. + public MigrationEntryMapper() + { + BuildMap(); + } + + #region Overrides of BaseMapper + + internal override ConcurrentDictionary PropertyInfoCache + { + get { return PropertyInfoCacheInstance; } + } + + internal override void BuildMap() + { + CacheMap(src => src.Id, dto => dto.Id); + CacheMap(src => src.CreateDate, dto => dto.CreateDate); + CacheMap(src => src.UpdateDate, dto => dto.CreateDate); + CacheMap(src => src.Version, dto => dto.Version); + CacheMap(src => src.MigrationName, dto => dto.Name); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Mappers/ServerRegistrationMapper.cs b/src/Umbraco.Core/Persistence/Mappers/ServerRegistrationMapper.cs index 40a18adc59..e532db18aa 100644 --- a/src/Umbraco.Core/Persistence/Mappers/ServerRegistrationMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/ServerRegistrationMapper.cs @@ -7,6 +7,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Mappers { [MapperFor(typeof(ServerRegistration))] + [MapperFor(typeof(IServerRegistration))] internal sealed class ServerRegistrationMapper : BaseMapper { private static readonly ConcurrentDictionary PropertyInfoCacheInstance = new ConcurrentDictionary(); diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMigrationEntryRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMigrationEntryRepository.cs new file mode 100644 index 0000000000..ff0a339a61 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMigrationEntryRepository.cs @@ -0,0 +1,9 @@ +using Umbraco.Core.Models; + +namespace Umbraco.Core.Persistence.Repositories +{ + public interface IMigrationEntryRepository : IRepositoryQueryable + { + + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IServerRegistrationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IServerRegistrationRepository.cs new file mode 100644 index 0000000000..5db9c6087e --- /dev/null +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IServerRegistrationRepository.cs @@ -0,0 +1,10 @@ +using System; +using Umbraco.Core.Models; + +namespace Umbraco.Core.Persistence.Repositories +{ + public interface IServerRegistrationRepository : IRepositoryQueryable + { + void DeactiveStaleServers(TimeSpan staleTimeout); + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/MigrationEntryRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MigrationEntryRepository.cs new file mode 100644 index 0000000000..657a1698eb --- /dev/null +++ b/src/Umbraco.Core/Persistence/Repositories/MigrationEntryRepository.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Logging; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Persistence.Factories; +using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Core.Persistence.UnitOfWork; + +namespace Umbraco.Core.Persistence.Repositories +{ + internal class MigrationEntryRepository : PetaPocoRepositoryBase, IMigrationEntryRepository + { + public MigrationEntryRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) + { + } + + protected override IMigrationEntry PerformGet(int id) + { + var sql = GetBaseQuery(false); + sql.Where(GetBaseWhereClause(), new { Id = id }); + + var dto = Database.First(sql); + if (dto == null) + return null; + + var factory = new MigrationEntryFactory(); + var entity = factory.BuildEntity(dto); + + //on initial construction we don't want to have dirty properties tracked + // http://issues.umbraco.org/issue/U4-1946 + entity.ResetDirtyProperties(false); + + return entity; + } + + protected override IEnumerable PerformGetAll(params int[] ids) + { + var factory = new MigrationEntryFactory(); + + if (ids.Any()) + { + return Database.Fetch("WHERE id in (@ids)", new { ids = ids }) + .Select(x => factory.BuildEntity(x)); + } + + return Database.Fetch("WHERE id > 0") + .Select(x => factory.BuildEntity(x)); + } + + protected override IEnumerable PerformGetByQuery(IQuery query) + { + var factory = new MigrationEntryFactory(); + var sqlClause = GetBaseQuery(false); + var translator = new SqlTranslator(sqlClause, query); + var sql = translator.Translate(); + + return Database.Fetch(sql).Select(x => factory.BuildEntity(x)); + } + + protected override Sql GetBaseQuery(bool isCount) + { + var sql = new Sql(); + sql.Select(isCount ? "COUNT(*)" : "*") + .From(SqlSyntax); + return sql; + } + + protected override string GetBaseWhereClause() + { + return "id = @Id"; + } + + protected override IEnumerable GetDeleteClauses() + { + var list = new List + { + "DELETE FROM umbracoMigration WHERE id = @Id" + }; + return list; + } + + protected override Guid NodeObjectTypeId + { + get { throw new NotImplementedException(); } + } + + protected override void PersistNewItem(IMigrationEntry entity) + { + ((MigrationEntry)entity).AddingEntity(); + + var factory = new MigrationEntryFactory(); + var dto = factory.BuildDto(entity); + + var id = Convert.ToInt32(Database.Insert(dto)); + entity.Id = id; + + entity.ResetDirtyProperties(); + } + + protected override void PersistUpdatedItem(IMigrationEntry entity) + { + ((MigrationEntry)entity).UpdatingEntity(); + + var factory = new MigrationEntryFactory(); + var dto = factory.BuildDto(entity); + + Database.Update(dto); + + entity.ResetDirtyProperties(); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/ServerRegistrationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ServerRegistrationRepository.cs index 1ef87357ea..eeadceebdb 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ServerRegistrationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ServerRegistrationRepository.cs @@ -13,14 +13,14 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories { - internal class ServerRegistrationRepository : PetaPocoRepositoryBase + internal class ServerRegistrationRepository : PetaPocoRepositoryBase, IServerRegistrationRepository { public ServerRegistrationRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } - protected override ServerRegistration PerformGet(int id) + protected override IServerRegistration PerformGet(int id) { var sql = GetBaseQuery(false); sql.Where(GetBaseWhereClause(), new { Id = id }); @@ -39,45 +39,35 @@ namespace Umbraco.Core.Persistence.Repositories return entity; } - protected override IEnumerable PerformGetAll(params int[] ids) + protected override IEnumerable PerformGetAll(params int[] ids) { + var factory = new ServerRegistrationFactory(); + if (ids.Any()) { - foreach (var id in ids) - { - yield return Get(id); - } - } - else - { - var serverDtos = Database.Fetch("WHERE id > 0"); - foreach (var serverDto in serverDtos) - { - yield return Get(serverDto.Id); - } + return Database.Fetch("WHERE id in (@ids)", new { ids = ids }) + .Select(x => factory.BuildEntity(x)); } + + return Database.Fetch("WHERE id > 0") + .Select(x => factory.BuildEntity(x)); } - protected override IEnumerable PerformGetByQuery(IQuery query) + protected override IEnumerable PerformGetByQuery(IQuery query) { + var factory = new ServerRegistrationFactory(); var sqlClause = GetBaseQuery(false); - var translator = new SqlTranslator(sqlClause, query); + var translator = new SqlTranslator(sqlClause, query); var sql = translator.Translate(); - var dtos = Database.Fetch(sql); - - foreach (var dto in dtos) - { - yield return Get(dto.Id); - } - + return Database.Fetch(sql).Select(x => factory.BuildEntity(x)); } protected override Sql GetBaseQuery(bool isCount) { var sql = new Sql(); sql.Select(isCount ? "COUNT(*)" : "*") - .From(); + .From(SqlSyntax); return sql; } @@ -100,9 +90,9 @@ namespace Umbraco.Core.Persistence.Repositories get { throw new NotImplementedException(); } } - protected override void PersistNewItem(ServerRegistration entity) + protected override void PersistNewItem(IServerRegistration entity) { - entity.AddingEntity(); + ((ServerRegistration)entity).AddingEntity(); var factory = new ServerRegistrationFactory(); var dto = factory.BuildDto(entity); @@ -113,9 +103,9 @@ namespace Umbraco.Core.Persistence.Repositories entity.ResetDirtyProperties(); } - protected override void PersistUpdatedItem(ServerRegistration entity) + protected override void PersistUpdatedItem(IServerRegistration entity) { - entity.UpdatingEntity(); + ((ServerRegistration)entity).UpdatingEntity(); var factory = new ServerRegistrationFactory(); var dto = factory.BuildDto(entity); @@ -129,7 +119,7 @@ namespace Umbraco.Core.Persistence.Repositories { var timeoutDate = DateTime.UtcNow.Subtract(staleTimeout); - Database.Update("SET isActive=0 WHERE lastNotifiedDate < @timeoutDate", new {timeoutDate = timeoutDate}); + Database.Update("SET isActive=0 WHERE lastNotifiedDate < @timeoutDate", new { timeoutDate = timeoutDate }); } } diff --git a/src/Umbraco.Core/Persistence/RepositoryFactory.cs b/src/Umbraco.Core/Persistence/RepositoryFactory.cs index 356e876c54..787a06f005 100644 --- a/src/Umbraco.Core/Persistence/RepositoryFactory.cs +++ b/src/Umbraco.Core/Persistence/RepositoryFactory.cs @@ -216,7 +216,15 @@ namespace Umbraco.Core.Persistence _settings.Templates); } - internal virtual ServerRegistrationRepository CreateServerRegistrationRepository(IDatabaseUnitOfWork uow) + public virtual IMigrationEntryRepository CreateMigrationEntryRepository(IDatabaseUnitOfWork uow) + { + return new MigrationEntryRepository( + uow, + CacheHelper.CreateDisabledCacheHelper(), //never cache + _logger, _sqlSyntax); + } + + public virtual IServerRegistrationRepository CreateServerRegistrationRepository(IDatabaseUnitOfWork uow) { return new ServerRegistrationRepository( uow, diff --git a/src/Umbraco.Core/Services/IMigrationEntryService.cs b/src/Umbraco.Core/Services/IMigrationEntryService.cs new file mode 100644 index 0000000000..29984cf1c5 --- /dev/null +++ b/src/Umbraco.Core/Services/IMigrationEntryService.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using Umbraco.Core.Models; + +namespace Umbraco.Core.Services +{ + public interface IMigrationEntryService + { + /// + /// Creates a migration entry, will throw an exception if it already exists + /// + /// + /// + /// + IMigrationEntry CreateEntry(string migrationName, Version version); + + /// + /// Finds a migration by name and version, returns null if not found + /// + /// + /// + /// + IMigrationEntry FindEntry(string migrationName, Version version); + + /// + /// Gets all entries for a given migration name + /// + /// + /// + IEnumerable GetAll(string migrationName); + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Services/IServerRegistrationService.cs b/src/Umbraco.Core/Services/IServerRegistrationService.cs new file mode 100644 index 0000000000..c0bacb5c40 --- /dev/null +++ b/src/Umbraco.Core/Services/IServerRegistrationService.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using Umbraco.Core.Models; + +namespace Umbraco.Core.Services +{ + public interface IServerRegistrationService + { + /// + /// Touches a server to mark it as active; deactivate stale servers. + /// + /// The server url. + /// The server unique identity. + /// The time after which a server is considered stale. + void TouchServer(string serverAddress, string serverIdentity, TimeSpan staleTimeout); + + /// + /// Deactivates a server. + /// + /// The server unique identity. + void DeactiveServer(string serverIdentity); + + /// + /// Deactivates stale servers. + /// + /// The time after which a server is considered stale. + void DeactiveStaleServers(TimeSpan staleTimeout); + + /// + /// Return all active servers. + /// + /// + IEnumerable GetActiveServers(); + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Services/MigrationEntryService.cs b/src/Umbraco.Core/Services/MigrationEntryService.cs new file mode 100644 index 0000000000..34a57e08e8 --- /dev/null +++ b/src/Umbraco.Core/Services/MigrationEntryService.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Logging; +using Umbraco.Core.Models; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.UnitOfWork; + +namespace Umbraco.Core.Services +{ + /// + /// Manages migration entries in the database + /// + public sealed class MigrationEntryService : RepositoryService, IMigrationEntryService + { + public MigrationEntryService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger) + : base(provider, repositoryFactory, logger) + { + } + + /// + /// Creates a migration entry, will throw an exception if it already exists + /// + /// + /// + /// + public IMigrationEntry CreateEntry(string migrationName, Version version) + { + var entry = new MigrationEntry + { + MigrationName = migrationName, + Version = version + }; + + var uow = UowProvider.GetUnitOfWork(); + using (var repo = RepositoryFactory.CreateMigrationEntryRepository(uow)) + { + repo.AddOrUpdate(entry); + uow.Commit(); + } + + return entry; + } + + /// + /// Finds a migration by name and version, returns null if not found + /// + /// + /// + /// + public IMigrationEntry FindEntry(string migrationName, Version version) + { + var uow = UowProvider.GetUnitOfWork(); + using (var repo = RepositoryFactory.CreateMigrationEntryRepository(uow)) + { + var query = Query.Builder + .Where(x => x.MigrationName.ToUpper() == migrationName.ToUpper() && x.Version == version); + return repo.GetByQuery(query).FirstOrDefault(); + } + } + + /// + /// Gets all entries for a given migration name + /// + /// + /// + public IEnumerable GetAll(string migrationName) + { + var uow = UowProvider.GetUnitOfWork(); + using (var repo = RepositoryFactory.CreateMigrationEntryRepository(uow)) + { + var query = Query.Builder + .Where(x => x.MigrationName.ToUpper() == migrationName.ToUpper()); + return repo.GetByQuery(query); + } + } + + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Services/ServerRegistrationService.cs b/src/Umbraco.Core/Services/ServerRegistrationService.cs index 157e7b795d..2812a9d1b8 100644 --- a/src/Umbraco.Core/Services/ServerRegistrationService.cs +++ b/src/Umbraco.Core/Services/ServerRegistrationService.cs @@ -9,11 +9,10 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Services { - /// /// Manages server registrations in the database. /// - public sealed class ServerRegistrationService : RepositoryService + public sealed class ServerRegistrationService : RepositoryService, IServerRegistrationService { /// /// Initializes a new instance of the class. @@ -36,14 +35,14 @@ namespace Umbraco.Core.Services var uow = UowProvider.GetUnitOfWork(); using (var repo = RepositoryFactory.CreateServerRegistrationRepository(uow)) { - var query = Query.Builder.Where(x => x.ServerIdentity.ToUpper() == serverIdentity.ToUpper()); + var query = Query.Builder.Where(x => x.ServerIdentity.ToUpper() == serverIdentity.ToUpper()); var server = repo.GetByQuery(query).FirstOrDefault(); if (server == null) { server = new ServerRegistration(serverAddress, serverIdentity, DateTime.UtcNow) { IsActive = true - }; + }; } else { @@ -67,7 +66,7 @@ namespace Umbraco.Core.Services var uow = UowProvider.GetUnitOfWork(); using (var repo = RepositoryFactory.CreateServerRegistrationRepository(uow)) { - var query = Query.Builder.Where(x => x.ServerIdentity.ToUpper() == serverIdentity.ToUpper()); + var query = Query.Builder.Where(x => x.ServerIdentity.ToUpper() == serverIdentity.ToUpper()); var server = repo.GetByQuery(query).FirstOrDefault(); if (server != null) { @@ -95,12 +94,12 @@ namespace Umbraco.Core.Services /// Return all active servers. /// /// - public IEnumerable GetActiveServers() + public IEnumerable GetActiveServers() { var uow = UowProvider.GetUnitOfWork(); using (var repo = RepositoryFactory.CreateServerRegistrationRepository(uow)) { - var query = Query.Builder.Where(x => x.IsActive); + var query = Query.Builder.Where(x => x.IsActive); return repo.GetByQuery(query).ToArray(); } } diff --git a/src/Umbraco.Core/Services/ServiceContext.cs b/src/Umbraco.Core/Services/ServiceContext.cs index 71e243af60..c1aacb550e 100644 --- a/src/Umbraco.Core/Services/ServiceContext.cs +++ b/src/Umbraco.Core/Services/ServiceContext.cs @@ -18,6 +18,7 @@ namespace Umbraco.Core.Services /// public class ServiceContext { + private Lazy _migrationEntryService; private Lazy _publicAccessService; private Lazy _taskService; private Lazy _domainService; @@ -33,7 +34,7 @@ namespace Umbraco.Core.Services private Lazy _fileService; private Lazy _localizationService; private Lazy _packagingService; - private Lazy _serverRegistrationService; + private Lazy _serverRegistrationService; private Lazy _entityService; private Lazy _relationService; private Lazy _treeService; @@ -70,6 +71,8 @@ namespace Umbraco.Core.Services /// /// /// + /// + /// public ServiceContext( IContentService contentService = null, IMediaService mediaService = null, @@ -94,8 +97,10 @@ namespace Umbraco.Core.Services ITaskService taskService = null, IMacroService macroService = null, IPublicAccessService publicAccessService = null, - IExternalLoginService externalLoginService = null) + IExternalLoginService externalLoginService = null, + IMigrationEntryService migrationEntryService = null) { + if (migrationEntryService != null) _migrationEntryService = new Lazy(() => migrationEntryService); if (externalLoginService != null) _externalLoginService = new Lazy(() => externalLoginService); if (auditService != null) _auditService = new Lazy(() => auditService); if (localizedTextService != null) _localizedTextService = new Lazy(() => localizedTextService); @@ -149,6 +154,9 @@ namespace Umbraco.Core.Services var provider = dbUnitOfWorkProvider; var fileProvider = fileUnitOfWorkProvider; + if (_migrationEntryService == null) + _migrationEntryService = new Lazy(() => new MigrationEntryService(provider, repositoryFactory, logger)); + if (_externalLoginService == null) _externalLoginService = new Lazy(() => new ExternalLoginService(provider, repositoryFactory, logger)); @@ -205,7 +213,7 @@ namespace Umbraco.Core.Services _notificationService = new Lazy(() => new NotificationService(provider, _userService.Value, _contentService.Value, logger)); if (_serverRegistrationService == null) - _serverRegistrationService = new Lazy(() => new ServerRegistrationService(provider, repositoryFactory, logger)); + _serverRegistrationService = new Lazy(() => new ServerRegistrationService(provider, repositoryFactory, logger)); if (_userService == null) _userService = new Lazy(() => new UserService(provider, repositoryFactory, logger)); @@ -263,6 +271,14 @@ namespace Umbraco.Core.Services } + /// + /// Gets the + /// + public IMigrationEntryService MigrationEntryService + { + get { return _migrationEntryService.Value; } + } + /// /// Gets the /// @@ -314,7 +330,7 @@ namespace Umbraco.Core.Services /// /// Gets the /// - public ServerRegistrationService ServerRegistrationService + public IServerRegistrationService ServerRegistrationService { get { return _serverRegistrationService.Value; } } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index ead0e5d1e2..2259044292 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -340,6 +340,9 @@ + + + @@ -358,15 +361,18 @@ + + + @@ -401,9 +407,12 @@ + + + @@ -429,9 +438,12 @@ + + + diff --git a/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs index c32e214177..b94339970f 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs @@ -128,7 +128,7 @@ namespace Umbraco.Tests.Persistence.Repositories using (var repository = CreateRepositor(unitOfWork)) { // Act - var query = Query.Builder.Where(x => x.ServerIdentity.ToUpper() == "COMPUTER3"); + var query = Query.Builder.Where(x => x.ServerIdentity.ToUpper() == "COMPUTER3"); var result = repository.GetByQuery(query); // Assert @@ -145,7 +145,7 @@ namespace Umbraco.Tests.Persistence.Repositories using (var repository = CreateRepositor(unitOfWork)) { // Act - var query = Query.Builder.Where(x => x.ServerAddress.StartsWith("http://")); + var query = Query.Builder.Where(x => x.ServerAddress.StartsWith("http://")); int count = repository.Count(query); // Assert