Merge origin/dev-v7 into dev-v7.6

This commit is contained in:
Stephan
2016-11-18 09:52:45 +01:00
22 changed files with 380 additions and 251 deletions
+1 -1
View File
@@ -141,5 +141,5 @@ build/docs.zip
build/ui-docs.zip
build/csharp-docs.zip
build/msbuild.log
.vs/
src/packages/
+16 -11
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Threading;
@@ -30,12 +31,13 @@ using Umbraco.Core.Manifest;
using Umbraco.Core.Services;
using Umbraco.Core.Sync;
using Umbraco.Core.Strings;
using IntegerValidator = Umbraco.Core.PropertyEditors.IntegerValidator;
using MigrationsVersionFourNineZero = Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionFourNineZero;
namespace Umbraco.Core
{
/// <summary>
/// A bootstrapper for the Umbraco application which initializes all objects for the Core of the application
/// A bootstrapper for the Umbraco application which initializes all objects for the Core of the application
/// </summary>
/// <remarks>
/// This does not provide any startup functionality relating to web objects
@@ -191,14 +193,14 @@ namespace Umbraco.Core
protected virtual CacheHelper CreateApplicationCache()
{
var cacheHelper = new CacheHelper(
//we need to have the dep clone runtime cache provider to ensure
//we need to have the dep clone runtime cache provider to ensure
//all entities are cached properly (cloned in and cloned out)
new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()),
new StaticCacheProvider(),
//we have no request based cache when not running in web-based context
new NullCacheProvider(),
new IsolatedRuntimeCache(type =>
//we need to have the dep clone runtime cache provider to ensure
//we need to have the dep clone runtime cache provider to ensure
//all entities are cached properly (cloned in and cloned out)
new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())));
@@ -251,18 +253,18 @@ namespace Umbraco.Core
}
/// <summary>
/// Special method to initialize the ApplicationEventsResolver and any modifications required for it such
/// Special method to initialize the ApplicationEventsResolver and any modifications required for it such
/// as adding custom types to the resolver.
/// </summary>
protected virtual void InitializeApplicationEventsResolver()
{
//find and initialize the application startup handlers, we need to initialize this resolver here because
//it is a special resolver where they need to be instantiated first before any other resolvers in order to bind to
//it is a special resolver where they need to be instantiated first before any other resolvers in order to bind to
//events and to call their events during bootup.
//ApplicationStartupHandler.RegisterHandlers();
//... and set the special flag to let us resolve before frozen resolution
ApplicationEventsResolver.Current = new ApplicationEventsResolver(
ServiceProvider,
ServiceProvider,
ProfilingLogger.Logger,
PluginManager.ResolveApplicationStartupHandlers())
{
@@ -282,7 +284,7 @@ namespace Umbraco.Core
}
/// <summary>
/// Fires after initialization and calls the callback to allow for customizations to occur &
/// Fires after initialization and calls the callback to allow for customizations to occur &
/// Ensure that the OnApplicationStarting methods of the IApplicationEvents are called
/// </summary>
/// <param name="afterStartup"></param>
@@ -334,7 +336,7 @@ namespace Umbraco.Core
{
if (_isComplete)
throw new InvalidOperationException("The boot manager has already been completed");
FreezeResolution();
//Here we need to make sure the db can be connected to
@@ -366,7 +368,7 @@ namespace Umbraco.Core
ProfilingLogger.Logger.Error<CoreBootManager>("An error occurred running OnApplicationStarted for handler " + x.GetType(), ex);
throw;
}
});
});
}
//Now, startup all of our legacy startup handler
@@ -455,6 +457,10 @@ namespace Umbraco.Core
{
ServerRegistrarResolver.Current = new ServerRegistrarResolver(new ConfigServerRegistrar());
}
else if ("true".InvariantEquals(ConfigurationManager.AppSettings["umbracoDisableElectionForSingleServer"]))
{
ServerRegistrarResolver.Current = new ServerRegistrarResolver(new SingleServerRegistrar());
}
else
{
ServerRegistrarResolver.Current = new ServerRegistrarResolver(
@@ -462,7 +468,6 @@ namespace Umbraco.Core
new Lazy<IServerRegistrationService>(() => ApplicationContext.Services.ServerRegistrationService),
new DatabaseServerRegistrarOptions()));
}
//by default we'll use the database server messenger with default options (no callbacks),
// this will be overridden in the web startup
@@ -473,7 +478,7 @@ namespace Umbraco.Core
ServiceProvider, ProfilingLogger.Logger,
() => PluginManager.ResolveAssignedMapperTypes());
//RepositoryResolver.Current = new RepositoryResolver(
// new RepositoryFactory(ApplicationCache));
@@ -11,7 +11,6 @@ namespace Umbraco.Core.Models.Rdbms
{
[Column("id")]
[PrimaryKeyColumn]
[Index(IndexTypes.NonClustered, Name = "IX_cmsPropertyData")]
public int Id { get; set; }
[Column("contentNodeId")]
@@ -0,0 +1,38 @@
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
{
/// <summary>
/// See: http://issues.umbraco.org/issue/U4-9188
/// </summary>
[Migration("7.6.0", 0, GlobalSettings.UmbracoMigrationName)]
public class UpdateUniqueIndexOnCmsPropertyData : MigrationBase
{
public UpdateUniqueIndexOnCmsPropertyData(ISqlSyntaxProvider sqlSyntax, ILogger logger)
: base(sqlSyntax, logger)
{
}
public override void Up()
{
//tuple = tablename, indexname, columnname, unique
var indexes = SqlSyntax.GetDefinedIndexes(Context.Database).ToArray();
var found = indexes.FirstOrDefault(
x => x.Item1.InvariantEquals("cmsPropertyData")
&& x.Item2.InvariantEquals("IX_cmsPropertyData"));
if (found != null)
{
//drop the index
Delete.Index("IX_cmsPropertyData").OnTable("cmsPropertyData");
}
}
public override void Down()
{
}
}
}
+16 -3
View File
@@ -739,6 +739,11 @@ namespace Umbraco.Core.Persistence
/// <param name="take"></param>
internal virtual void BuildSqlDbSpecificPagingQuery(DBType databaseType, long skip, long take, string sql, string sqlSelectRemoved, string sqlOrderBy, ref object[] args, out string sqlPage)
{
// this is overriden in UmbracoDatabase, and if running SqlServer >=2012, the database type
// is switched from SqlServer to SqlServerCE in order to use the better paging syntax that
// SqlCE supports, and SqlServer >=2012 too.
// so the first case is actually for SqlServer <2012, and second case is CE *and* SqlServer >=2012
if (databaseType == DBType.SqlServer || databaseType == DBType.Oracle)
{
sqlSelectRemoved = rxOrderBy.Replace(sqlSelectRemoved, "");
@@ -746,8 +751,16 @@ namespace Umbraco.Core.Persistence
{
sqlSelectRemoved = "peta_inner.* FROM (SELECT " + sqlSelectRemoved + ") peta_inner";
}
sqlPage = string.Format("SELECT * FROM (SELECT ROW_NUMBER() OVER ({0}) peta_rn, {1}) peta_paged WHERE peta_rn>@{2} AND peta_rn<=@{3}",
sqlOrderBy == null ? "ORDER BY (SELECT NULL)" : sqlOrderBy, sqlSelectRemoved, args.Length, args.Length + 1);
// split to ensure that peta_rn is the last field to be selected, else Page<int> would fail
// the resulting sql is not perfect, NPoco has a much nicer way to do it, but it would require
// importing large parts of NPoco
var pos = sqlSelectRemoved.IndexOf("FROM");
var sqlColumns = sqlSelectRemoved.Substring(0, pos);
var sqlFrom = sqlSelectRemoved.Substring(pos);
sqlPage = string.Format("SELECT * FROM (SELECT {0}, ROW_NUMBER() OVER ({1}) peta_rn {2}) peta_paged WHERE peta_rn>@{3} AND peta_rn<=@{4}",
sqlColumns, sqlOrderBy ?? "ORDER BY (SELECT NULL)", sqlFrom, args.Length, args.Length + 1);
args = args.Concat(new object[] { skip, skip + take }).ToArray();
}
else if (databaseType == DBType.SqlServerCE)
@@ -774,7 +787,7 @@ namespace Umbraco.Core.Persistence
throw new Exception("Unable to parse SQL statement for paged query");
if (_dbType == DBType.Oracle && sqlSelectRemoved.StartsWith("*"))
throw new Exception("Query must alias '*' when performing a paged query.\neg. select t.* from table t order by t.id");
BuildSqlDbSpecificPagingQuery(_dbType, skip, take, sql, sqlSelectRemoved, sqlOrderBy, ref args, out sqlPage);
}
@@ -1,22 +1,14 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Net.Http.Headers;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Dynamics;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Persistence.Querying;
@@ -81,7 +73,7 @@ namespace Umbraco.Core.Persistence.Repositories
var sql = GetBaseQuery(false);
if (ids.Any())
{
sql.Where("umbracoNode.id in (@ids)", new { ids = ids });
sql.Where("umbracoNode.id in (@ids)", new { ids });
}
//we only want the newest ones with this method
@@ -224,6 +216,14 @@ namespace Umbraco.Core.Persistence.Repositories
}
}
public override IEnumerable<IContent> GetAllVersions(int id)
{
var sql = GetBaseQuery(false)
.Where(GetBaseWhereClause(), new { Id = id })
.OrderByDescending<ContentVersionDto>(x => x.VersionDate, SqlSyntax);
return ProcessQuery(sql, true);
}
public override IContent GetByVersion(Guid versionId)
{
var sql = GetBaseQuery(false);
@@ -633,29 +633,9 @@ namespace Umbraco.Core.Persistence.Repositories
.OrderBy<NodeDto>(x => x.Level, SqlSyntax)
.OrderBy<NodeDto>(x => x.SortOrder, SqlSyntax);
//NOTE: This doesn't allow properties to be part of the query
var dtos = Database.Fetch<DocumentDto, ContentVersionDto, ContentDto, NodeDto, DocumentPublishedReadOnlyDto>(sql);
foreach (var dto in dtos)
{
//Check in the cache first. If it exists there AND it is published
// then we can use that entity. Otherwise if it is not published (which can be the case
// because we only store the 'latest' entries in the cache which might not be the published
// version)
var fromCache = RuntimeCache.GetCacheItem<IContent>(GetCacheIdKey<IContent>(dto.NodeId));
//var fromCache = TryGetFromCache(dto.NodeId);
if (fromCache != null && fromCache.Published)
{
yield return fromCache;
}
else
{
yield return CreateContentFromDto(dto, dto.VersionId, sql);
}
}
return ProcessQuery(sql, true);
}
/// <summary>
/// This builds the Xml document used for the XML cache
/// </summary>
@@ -829,7 +809,7 @@ order by umbracoNode.level, umbracoNode.parentID, umbracoNode.sortOrder";
return GetPagedResultsByQuery<DocumentDto, Content>(query, pageIndex, pageSize, out totalRecords,
new Tuple<string, string>("cmsDocument", "nodeId"),
ProcessQuery, orderBy, orderDirection, orderBySystemField,
sql => ProcessQuery(sql), orderBy, orderDirection, orderBySystemField,
filterCallback);
}
@@ -860,83 +840,79 @@ order by umbracoNode.level, umbracoNode.parentID, umbracoNode.sortOrder";
return base.GetDatabaseFieldNameForOrderBy(orderBy);
}
private IEnumerable<IContent> ProcessQuery(Sql sql)
private IEnumerable<IContent> ProcessQuery(Sql sql, bool withCache = false)
{
//NOTE: This doesn't allow properties to be part of the query
// fetch returns a list so it's ok to iterate it in this method
var dtos = Database.Fetch<DocumentDto, ContentVersionDto, ContentDto, NodeDto, DocumentPublishedReadOnlyDto>(sql);
if (dtos.Count == 0) return Enumerable.Empty<IContent>();
//nothing found
if (dtos.Any() == false) return Enumerable.Empty<IContent>();
var content = new IContent[dtos.Count];
var defs = new List<DocumentDefinition>();
var templateIds = new List<int>();
//content types
//NOTE: This should be ok for an SQL 'IN' statement, there shouldn't be an insane amount of content types
var contentTypes = _contentTypeRepository.GetAll(dtos.Select(x => x.ContentVersionDto.ContentDto.ContentTypeId).ToArray())
.ToArray();
var ids = dtos
.Where(dto => dto.TemplateId.HasValue && dto.TemplateId.Value > 0)
.Select(x => x.TemplateId.Value).ToArray();
//NOTE: This should be ok for an SQL 'IN' statement, there shouldn't be an insane amount of content types
var templates = ids.Length == 0 ? Enumerable.Empty<ITemplate>() : _templateRepository.GetAll(ids).ToArray();
var dtosWithContentTypes = dtos
//This select into and null check are required because we don't have a foreign damn key on the contentType column
// http://issues.umbraco.org/issue/U4-5503
.Select(x => new { dto = x, contentType = contentTypes.FirstOrDefault(ct => ct.Id == x.ContentVersionDto.ContentDto.ContentTypeId) })
.Where(x => x.contentType != null)
.ToArray();
//Go get the property data for each document
var docDefs = dtosWithContentTypes.Select(d => new DocumentDefinition(
d.dto.NodeId,
d.dto.VersionId,
d.dto.ContentVersionDto.VersionDate,
d.dto.ContentVersionDto.ContentDto.NodeDto.CreateDate,
d.contentType));
var propertyData = GetPropertyCollection(sql, docDefs);
return dtosWithContentTypes.Select(d => CreateContentFromDto(
d.dto,
contentTypes.First(ct => ct.Id == d.dto.ContentVersionDto.ContentDto.ContentTypeId),
templates.FirstOrDefault(tem => tem.Id == (d.dto.TemplateId.HasValue ? d.dto.TemplateId.Value : -1)),
propertyData[d.dto.NodeId]));
}
/// <summary>
/// Private method to create a content object from a DocumentDto, which is used by Get and GetByVersion.
/// </summary>
/// <param name="dto"></param>
/// <param name="contentType"></param>
/// <param name="template"></param>
/// <param name="propCollection"></param>
/// <returns></returns>
private IContent CreateContentFromDto(DocumentDto dto,
IContentType contentType,
ITemplate template,
Models.PropertyCollection propCollection)
{
var factory = new ContentFactory(contentType, NodeObjectTypeId, dto.NodeId);
var content = factory.BuildEntity(dto);
//Check if template id is set on DocumentDto, and get ITemplate if it is.
if (dto.TemplateId.HasValue && dto.TemplateId.Value > 0)
for (var i = 0; i < dtos.Count; i++)
{
content.Template = template ?? _templateRepository.Get(dto.TemplateId.Value);
}
else
{
//ensure there isn't one set.
content.Template = null;
var dto = dtos[i];
// if the cache contains the published version, use it
if (withCache)
{
var cached = RuntimeCache.GetCacheItem<IContent>(GetCacheIdKey<IContent>(dto.NodeId));
if (cached != null && cached.Published)
{
content[i] = cached;
continue;
}
}
// else, need to fetch from the database
// content type repository is full-cache so OK to get each one independently
var contentType = _contentTypeRepository.Get(dto.ContentVersionDto.ContentDto.ContentTypeId);
var factory = new ContentFactory(contentType, NodeObjectTypeId, dto.NodeId);
content[i] = factory.BuildEntity(dto);
// need template
if (dto.TemplateId.HasValue && dto.TemplateId.Value > 0)
templateIds.Add(dto.TemplateId.Value);
// need properties
defs.Add(new DocumentDefinition(
dto.NodeId,
dto.VersionId,
dto.ContentVersionDto.VersionDate,
dto.ContentVersionDto.ContentDto.NodeDto.CreateDate,
contentType
));
}
content.Properties = propCollection;
// load all required templates in 1 query
var templates = _templateRepository.GetAll(templateIds.ToArray())
.ToDictionary(x => x.Id, x => x);
// load all properties for all documents from database in 1 query
var propertyData = GetPropertyCollection(sql, defs);
// assign
var dtoIndex = 0;
foreach (var def in defs)
{
// move to corresponding item (which has to exist)
while (dtos[dtoIndex].NodeId != def.Id) dtoIndex++;
// complete the item
var cc = content[dtoIndex];
var dto = dtos[dtoIndex];
ITemplate template = null;
if (dto.TemplateId.HasValue)
templates.TryGetValue(dto.TemplateId.Value, out template); // else null
cc.Template = template;
cc.Properties = propertyData[cc.Id];
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
((Entity) cc).ResetDirtyProperties(false);
}
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
((Entity)content).ResetDirtyProperties(false);
return content;
}
@@ -4,21 +4,17 @@ using System.Globalization;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Dynamics;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Cache;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Services;
namespace Umbraco.Core.Persistence.Repositories
{
@@ -137,6 +133,74 @@ namespace Umbraco.Core.Persistence.Repositories
#region Overrides of VersionableRepositoryBase<IContent>
public override IEnumerable<IMedia> GetAllVersions(int id)
{
var sql = GetBaseQuery(false)
.Where(GetBaseWhereClause(), new { Id = id })
.OrderByDescending<ContentVersionDto>(x => x.VersionDate, SqlSyntax);
return ProcessQuery(sql, true);
}
private IEnumerable<IMedia> ProcessQuery(Sql sql, bool withCache = false)
{
// fetch returns a list so it's ok to iterate it in this method
var dtos = Database.Fetch<ContentVersionDto, ContentDto, NodeDto>(sql);
var content = new IMedia[dtos.Count];
var defs = new List<DocumentDefinition>();
for (var i = 0; i < dtos.Count; i++)
{
var dto = dtos[i];
// if the cache contains the item, use it
if (withCache)
{
var cached = RuntimeCache.GetCacheItem<IMedia>(GetCacheIdKey<IMedia>(dto.NodeId));
if (cached != null)
{
content[i] = cached;
continue;
}
}
// else, need to fetch from the database
// content type repository is full-cache so OK to get each one independently
var contentType = _mediaTypeRepository.Get(dto.ContentDto.ContentTypeId);
var factory = new MediaFactory(contentType, NodeObjectTypeId, dto.NodeId);
content[i] = factory.BuildEntity(dto);
// need properties
defs.Add(new DocumentDefinition(
dto.NodeId,
dto.VersionId,
dto.VersionDate,
dto.ContentDto.NodeDto.CreateDate,
contentType
));
}
// load all properties for all documents from database in 1 query
var propertyData = GetPropertyCollection(sql, defs);
// assign
var dtoIndex = 0;
foreach (var def in defs)
{
// move to corresponding item (which has to exist)
while (dtos[dtoIndex].NodeId != def.Id) dtoIndex++;
// complete the item
var cc = content[dtoIndex];
cc.Properties = propertyData[cc.Id];
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
((Entity) cc).ResetDirtyProperties(false);
}
return content;
}
public override IMedia GetByVersion(Guid versionId)
{
var sql = GetBaseQuery(false);
@@ -431,7 +495,7 @@ namespace Umbraco.Core.Persistence.Repositories
return GetPagedResultsByQuery<ContentVersionDto, Models.Media>(query, pageIndex, pageSize, out totalRecords,
new Tuple<string, string>("cmsContentVersion", "contentId"),
ProcessQuery, orderBy, orderDirection, orderBySystemField,
sql => ProcessQuery(sql), orderBy, orderDirection, orderBySystemField,
filterCallback);
}
@@ -460,62 +524,6 @@ namespace Umbraco.Core.Persistence.Repositories
return pagedResult.Items.Select(dto => XElement.Parse(dto.Xml));
}
private IEnumerable<IMedia> ProcessQuery(Sql sql)
{
//NOTE: This doesn't allow properties to be part of the query
var dtos = Database.Fetch<ContentVersionDto, ContentDto, NodeDto>(sql);
var ids = dtos.Select(x => x.ContentDto.ContentTypeId).ToArray();
//content types
var contentTypes = ids.Length == 0 ? Enumerable.Empty<IMediaType>() : _mediaTypeRepository.GetAll(ids).ToArray();
var dtosWithContentTypes = dtos
//This select into and null check are required because we don't have a foreign damn key on the contentType column
// http://issues.umbraco.org/issue/U4-5503
.Select(x => new { dto = x, contentType = contentTypes.FirstOrDefault(ct => ct.Id == x.ContentDto.ContentTypeId) })
.Where(x => x.contentType != null)
.ToArray();
//Go get the property data for each document
var docDefs = dtosWithContentTypes.Select(d => new DocumentDefinition(
d.dto.NodeId,
d.dto.VersionId,
d.dto.VersionDate,
d.dto.ContentDto.NodeDto.CreateDate,
d.contentType))
.ToArray();
var propertyData = GetPropertyCollection(sql, docDefs);
return dtosWithContentTypes.Select(d => CreateMediaFromDto(
d.dto,
contentTypes.First(ct => ct.Id == d.dto.ContentDto.ContentTypeId),
propertyData[d.dto.NodeId]));
}
/// <summary>
/// Private method to create a media object from a ContentDto
/// </summary>
/// <param name="d"></param>
/// <param name="contentType"></param>
/// <param name="propCollection"></param>
/// <returns></returns>
private IMedia CreateMediaFromDto(ContentVersionDto dto,
IMediaType contentType,
PropertyCollection propCollection)
{
var factory = new MediaFactory(contentType, NodeObjectTypeId, dto.NodeId);
var media = factory.BuildEntity(dto);
media.Properties = propCollection;
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
((Entity)media).ResetDirtyProperties(false);
return media;
}
/// <summary>
/// Private method to create a media object from a ContentDto
/// </summary>
@@ -2,24 +2,19 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Xml.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Cache;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.Relators;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Dynamics;
namespace Umbraco.Core.Persistence.Repositories
{
@@ -380,6 +375,14 @@ namespace Umbraco.Core.Persistence.Repositories
#region Overrides of VersionableRepositoryBase<IMembershipUser>
public override IEnumerable<IMember> GetAllVersions(int id)
{
var sql = GetBaseQuery(false)
.Where(GetBaseWhereClause(), new { Id = id })
.OrderByDescending<ContentVersionDto>(x => x.VersionDate, SqlSyntax);
return ProcessQuery(sql, true);
}
public void RebuildXmlStructures(Func<IMember, XElement> serializer, int groupSize = 200, IEnumerable<int> contentTypeIds = null)
{
// the previous way of doing this was to run it all in one big transaction,
@@ -616,7 +619,7 @@ namespace Umbraco.Core.Persistence.Repositories
return GetPagedResultsByQuery<MemberDto, Member>(query, pageIndex, pageSize, out totalRecords,
new Tuple<string, string>("cmsMember", "nodeId"),
ProcessQuery, orderBy, orderDirection, orderBySystemField,
sql => ProcessQuery(sql), orderBy, orderDirection, orderBySystemField,
filterCallback);
}
@@ -656,59 +659,65 @@ namespace Umbraco.Core.Persistence.Repositories
return base.GetEntityPropertyNameForOrderBy(orderBy);
}
private IEnumerable<IMember> ProcessQuery(Sql sql)
private IEnumerable<IMember> ProcessQuery(Sql sql, bool withCache = false)
{
//NOTE: This doesn't allow properties to be part of the query
// fetch returns a list so it's ok to iterate it in this method
var dtos = Database.Fetch<MemberDto, ContentVersionDto, ContentDto, NodeDto>(sql);
var ids = dtos.Select(x => x.ContentVersionDto.ContentDto.ContentTypeId).ToArray();
var content = new IMember[dtos.Count];
var defs = new List<DocumentDefinition>();
//content types
var contentTypes = ids.Length == 0 ? Enumerable.Empty<IMemberType>() : _memberTypeRepository.GetAll(ids).ToArray();
for (var i = 0; i < dtos.Count; i++)
{
var dto = dtos[i];
var dtosWithContentTypes = dtos
//This select into and null check are required because we don't have a foreign damn key on the contentType column
// http://issues.umbraco.org/issue/U4-5503
.Select(x => new { dto = x, contentType = contentTypes.FirstOrDefault(ct => ct.Id == x.ContentVersionDto.ContentDto.ContentTypeId) })
.Where(x => x.contentType != null)
.ToArray();
// if the cache contains the item, use it
if (withCache)
{
var cached = RuntimeCache.GetCacheItem<IMember>(GetCacheIdKey<IMember>(dto.NodeId));
if (cached != null)
{
content[i] = cached;
continue;
}
}
//Go get the property data for each document
IEnumerable<DocumentDefinition> docDefs = dtosWithContentTypes.Select(d => new DocumentDefinition(
d.dto.NodeId,
d.dto.ContentVersionDto.VersionId,
d.dto.ContentVersionDto.VersionDate,
d.dto.ContentVersionDto.ContentDto.NodeDto.CreateDate,
d.contentType));
// else, need to fetch from the database
// content type repository is full-cache so OK to get each one independently
var contentType = _memberTypeRepository.Get(dto.ContentVersionDto.ContentDto.ContentTypeId);
var factory = new MemberFactory(contentType, NodeObjectTypeId, dto.NodeId);
content[i] = factory.BuildEntity(dto);
var propertyData = GetPropertyCollection(sql, docDefs);
// need properties
defs.Add(new DocumentDefinition(
dto.NodeId,
dto.ContentVersionDto.VersionId,
dto.ContentVersionDto.VersionDate,
dto.ContentVersionDto.ContentDto.NodeDto.CreateDate,
contentType
));
}
return dtosWithContentTypes.Select(d => CreateMemberFromDto(
d.dto,
contentTypes.First(ct => ct.Id == d.dto.ContentVersionDto.ContentDto.ContentTypeId),
propertyData[d.dto.NodeId]));
}
// load all properties for all documents from database in 1 query
var propertyData = GetPropertyCollection(sql, defs);
/// <summary>
/// Private method to create a member object from a MemberDto
/// </summary>
/// <param name="dto"></param>
/// <param name="contentType"></param>
/// <param name="propCollection"></param>
/// <returns></returns>
private IMember CreateMemberFromDto(MemberDto dto,
IMemberType contentType,
PropertyCollection propCollection)
{
var factory = new MemberFactory(contentType, NodeObjectTypeId, dto.ContentVersionDto.NodeId);
var member = factory.BuildEntity(dto);
// assign
var dtoIndex = 0;
foreach (var def in defs)
{
// move to corresponding item (which has to exist)
while (dtos[dtoIndex].NodeId != def.Id) dtoIndex++;
member.Properties = propCollection;
// complete the item
var cc = content[dtoIndex];
cc.Properties = propertyData[cc.Id];
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
((Entity)member).ResetDirtyProperties(false);
return member;
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
((Entity)cc).ResetDirtyProperties(false);
}
return content;
}
/// <summary>
@@ -6,16 +6,11 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Persistence.SqlSyntax
{
/// <summary>
/// Represents an SqlSyntaxProvider for Sql Server
/// Represents an SqlSyntaxProvider for Sql Server.
/// </summary>
[SqlSyntaxProviderAttribute(Constants.DatabaseProviders.SqlServer)]
[SqlSyntaxProvider(Constants.DatabaseProviders.SqlServer)]
public class SqlServerSyntaxProvider : MicrosoftSqlSyntaxProviderBase<SqlServerSyntaxProvider>
{
public SqlServerSyntaxProvider()
{
}
/// <summary>
/// Gets/sets the version of the current SQL server instance
/// </summary>
@@ -31,7 +26,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
switch (firstPart)
{
case "13":
_versionName = SqlServerVersionName.V2014;
_versionName = SqlServerVersionName.V2016;
break;
case "12":
_versionName = SqlServerVersionName.V2014;
@@ -75,7 +70,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
{
var items = db.Fetch<dynamic>("SELECT TableName = t.Name,ColumnName = c.Name,dc.Name,dc.[Definition] FROM sys.tables t INNER JOIN sys.default_constraints dc ON t.object_id = dc.parent_object_id INNER JOIN sys.columns c ON dc.parent_object_id = c.object_id AND c.column_id = dc.parent_column_id");
return items.Select(x => new Tuple<string, string, string, string>(x.TableName, x.ColumnName, x.Name, x.Definition));
}
}
public override IEnumerable<string> GetTablesInSchema(Database db)
{
@@ -120,9 +115,9 @@ from sys.tables as T inner join sys.indexes as I on T.[object_id] = I.[object_id
inner join sys.all_columns as AC on IC.[object_id] = AC.[object_id] and IC.[column_id] = AC.[column_id]
WHERE I.name NOT LIKE 'PK_%'
order by T.name, I.name");
return items.Select(item => new Tuple<string, string, string, bool>(item.TABLE_NAME, item.INDEX_NAME, item.COLUMN_NAME,
return items.Select(item => new Tuple<string, string, string, bool>(item.TABLE_NAME, item.INDEX_NAME, item.COLUMN_NAME,
item.UNIQUE == 1)).ToList();
}
public override bool DoesTableExist(Database db, string tableName)
@@ -164,7 +159,7 @@ order by T.name, I.name");
switch (systemMethod)
{
case SystemMethods.NewGuid:
return "NEWID()";
return "NEWID()";
case SystemMethods.CurrentDateTime:
return "GETDATE()";
//case SystemMethods.NewSequentialId:
@@ -181,11 +176,11 @@ order by T.name, I.name");
get { return "ALTER TABLE [{0}] DROP CONSTRAINT [DF_{0}_{1}]"; }
}
public override string DropIndex { get { return "DROP INDEX {0} ON {1}"; } }
public override string RenameColumn { get { return "sp_rename '{0}.{1}', '{2}', 'COLUMN'"; } }
}
}
@@ -114,7 +114,8 @@ namespace Umbraco.Core.Sync
// - contain a scheme
// - end or not with a slash, it will be taken care of
// eg "http://www.mysite.com/umbraco"
var registrar = ServerRegistrarResolver.Current.Registrar as IServerRegistrar2;
var resolver = ServerRegistrarResolver.HasCurrent ? ServerRegistrarResolver.Current : null;
var registrar = resolver == null ? null : resolver.Registrar as IServerRegistrar2;
url = registrar == null ? null : registrar.GetCurrentServerUmbracoApplicationUrl();
if (url.IsNullOrWhiteSpace() == false)
{
@@ -0,0 +1,37 @@
using System.Collections.Generic;
namespace Umbraco.Core.Sync
{
public class SingleServerRegistrar : IServerRegistrar2
{
private readonly string _umbracoApplicationUrl;
public IEnumerable<IServerAddress> Registrations { get; private set; }
public SingleServerRegistrar()
{
_umbracoApplicationUrl = ApplicationContext.Current.UmbracoApplicationUrl;
Registrations = new[] { new ServerAddressImpl(_umbracoApplicationUrl) };
}
public ServerRole GetCurrentServerRole()
{
return ServerRole.Single;
}
public string GetCurrentServerUmbracoApplicationUrl()
{
return _umbracoApplicationUrl;
}
private class ServerAddressImpl : IServerAddress
{
public ServerAddressImpl(string serverAddress)
{
ServerAddress = serverAddress;
}
public string ServerAddress { get; private set; }
}
}
}
+2
View File
@@ -454,6 +454,7 @@
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFourZero\AddUniqueIdPropertyTypeGroupColumn.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFourZero\RemoveParentIdPropertyTypeGroupColumn.cs" />
<Compile Include="Persistence\Mappers\TaskTypeMapper.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\RemovePropertyDataIdIndex.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeTwo\EnsureMigrationsTableIdentityIsCorrect.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFourZero\EnsureContentTypeUniqueIdsAreConsistent.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddExternalLoginsTable.cs" />
@@ -1348,6 +1349,7 @@
<Compile Include="Sync\ApplicationUrlHelper.cs" />
<Compile Include="Sync\RefreshMethodType.cs" />
<Compile Include="Sync\ServerMessengerBase.cs" />
<Compile Include="Sync\SingleServerRegistrar.cs" />
<Compile Include="ThreadExtensions.cs" />
<Compile Include="TopologicalSorter.cs" />
<Compile Include="Strings\DefaultUrlSegmentProvider.cs" />
@@ -12,6 +12,7 @@
status: "",
progress:0
};
vm.installCompleted = false;
vm.zipFile = {
uploadStatus: "idle",
uploadProgress: 0,
@@ -137,10 +138,10 @@
localStorageService.set("packageInstallUri", "installed");
}
//reload on next digest (after cookie)
$timeout(function () {
$window.location.reload(true);
});
vm.installState.status = localizationService.localize("packager_installStateCompleted");
vm.installCompleted = true;
},
installError);
@@ -150,6 +151,13 @@
//This will return a rejection meaning that the promise change above will stop
return $q.reject();
}
vm.reloadPage = function() {
//reload on next digest (after cookie)
$timeout(function () {
$window.location.reload(true);
});
}
}
angular.module("umbraco").controller("Umbraco.Editors.Packages.InstallLocalController", PackagesInstallLocalController);
@@ -159,6 +159,19 @@
<p>{{vm.installState.status}}</p>
</div>
<div class="umb-info-local-item text-info"
ng-show="vm.installCompleted">
<button type="button"
class="btn btn-success flex-inline mt3"
ng-click="vm.reloadPage()">
Finish
</button>
</div>
</div>
</form>
@@ -30,6 +30,7 @@
vm.openLightbox = openLightbox;
vm.closeLightbox = closeLightbox;
vm.search = search;
vm.installCompleted = false;
var currSort = "Latest";
//used to cancel any request in progress if another one needs to take it's place
@@ -215,10 +216,8 @@
localStorageService.set("packageInstallUri", result.postInstallationPath);
}
//reload on next digest (after cookie)
$timeout(function() {
window.location.reload(true);
});
vm.installState.status = localizationService.localize("packager_installStateCompleted");
vm.installCompleted = true;
},
error);
@@ -277,6 +276,13 @@
searchDebounced();
}
vm.reloadPage = function () {
//reload on next digest (after cookie)
$timeout(function () {
window.location.reload(true);
});
}
init();
}
@@ -340,6 +340,16 @@
<p>{{vm.installState.status}}</p>
</div>
<div class="umb-info-local-item text-info"
ng-show="vm.installCompleted">
<button type="button"
class="btn btn-success flex-inline mt3"
ng-click="vm.reloadPage()">
Finish
</button>
</div>
</div>
</form>
+1
View File
@@ -2398,6 +2398,7 @@
<VSToolsPath Condition="exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v11.0\WebApplications\Microsoft.WebApplication.targets')">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v11.0</VSToolsPath>
<VSToolsPath Condition="exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v12.0\WebApplications\Microsoft.WebApplication.targets')">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v12.0</VSToolsPath>
<VSToolsPath Condition="exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v14.0\WebApplications\Microsoft.WebApplication.targets')">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v14.0</VSToolsPath>
<VSToolsPath Condition="exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v15.0\WebApplications\Microsoft.WebApplication.targets')">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v15.0</VSToolsPath>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
@@ -817,7 +817,7 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="installStateInstalling">Installing...</key>
<key alias="installStateRestarting">Restarting, please wait...</key>
<key alias="installStateComplete">All done, your browser will now refresh, please wait...</key>
<key alias="installStateCompleted">Please click finish to complete installation and reload page.</key>
</area>
<area alias="paste">
<key alias="doNothing">Paste with full formatting (Not recommended)</key>
@@ -817,6 +817,7 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="installStateInstalling">Installing...</key>
<key alias="installStateRestarting">Restarting, please wait...</key>
<key alias="installStateComplete">All done, your browser will now refresh, please wait...</key>
<key alias="installStateCompleted">Please click finish to complete installation and reload page.</key>
</area>
<area alias="paste">
<key alias="doNothing">Paste with full formatting (Not recommended)</key>
+1
View File
@@ -2258,6 +2258,7 @@
<VSToolsPath Condition="exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v11.0\WebApplications\Microsoft.WebApplication.targets')">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v11.0</VSToolsPath>
<VSToolsPath Condition="exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v12.0\WebApplications\Microsoft.WebApplication.targets')">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v12.0</VSToolsPath>
<VSToolsPath Condition="exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v14.0\WebApplications\Microsoft.WebApplication.targets')">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v14.0</VSToolsPath>
<VSToolsPath Condition="exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v15.0\WebApplications\Microsoft.WebApplication.targets')">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v15.0</VSToolsPath>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
+4
View File
@@ -55,6 +55,10 @@
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.Tasks.dll')">
<WebPublishingTasks>$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.Tasks.dll</WebPublishingTasks>
</PropertyGroup>
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v15.0\Web\Microsoft.Web.Publishing.Tasks.dll')">
<WebPublishingTasks>$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v15.0\Web\Microsoft.Web.Publishing.Tasks.dll</WebPublishingTasks>
</PropertyGroup>
<!--
****************************************************
+2
View File
@@ -127,7 +127,9 @@ Global
{4C4C194C-B5E4-4991-8F87-4373E24CC19F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4C4C194C-B5E4-4991-8F87-4373E24CC19F}.Release|Any CPU.Build.0 = Release|Any CPU
{3819A550-DCEC-4153-91B4-8BA9F7F0B9B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3819A550-DCEC-4153-91B4-8BA9F7F0B9B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3819A550-DCEC-4153-91B4-8BA9F7F0B9B4}.Release|Any CPU.ActiveCfg = Debug|Any CPU
{3819A550-DCEC-4153-91B4-8BA9F7F0B9B4}.Release|Any CPU.Build.0 = Debug|Any CPU
{651E1350-91B6-44B7-BD60-7207006D7003}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{651E1350-91B6-44B7-BD60-7207006D7003}.Debug|Any CPU.Build.0 = Debug|Any CPU
{651E1350-91B6-44B7-BD60-7207006D7003}.Release|Any CPU.ActiveCfg = Release|Any CPU