From f30aefb614204619c1e55da9ee8b3e5d814a6d9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 3 Jun 2019 12:04:14 +0200 Subject: [PATCH 01/10] parse dimensions to configuration of TinyMCE + remove autoresize if height is set. --- .../src/views/propertyeditors/rte/rte.controller.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js index 3c34890fa9..5bcd3b9330 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js @@ -41,10 +41,19 @@ angular.module("umbraco") $q.all(promises).then(function (result) { var standardConfig = result[promises.length - 1]; - + + var width = parseInt(editorConfig.dimensions.width, 10) || null + var height = parseInt(editorConfig.dimensions.height, 10) || null + + if (height !== null) { + standardConfig.plugins.splice(standardConfig.plugins.indexOf("autoresize"), 1); + } + //create a baseline Config to extend upon var baseLineConfigObj = { - maxImageSize: editorConfig.maxImageSize + maxImageSize: editorConfig.maxImageSize, + width: width, + height: height }; angular.extend(baseLineConfigObj, standardConfig); From 849feb06834a4c7bcea66c20ae8589ae11ff0b5d Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 3 Jun 2019 15:34:54 +0200 Subject: [PATCH 02/10] Fix UmbracoDatabaseFactory SqlServer detection --- .../Migrations/Install/DatabaseBuilder.cs | 4 +- .../Persistence/IUmbracoDatabaseFactory.cs | 24 ++- .../Persistence/UmbracoDatabaseFactory.cs | 178 +++++++++--------- .../Persistence/DatabaseContextTests.cs | 17 +- 4 files changed, 120 insertions(+), 103 deletions(-) diff --git a/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs b/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs index 5c4defab0c..6778d0a465 100644 --- a/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs +++ b/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs @@ -389,7 +389,7 @@ namespace Umbraco.Core.Migrations.Install private DatabaseSchemaResult ValidateSchema(IScope scope) { - if (_databaseFactory.Configured == false) + if (_databaseFactory.Initialized == false) return new DatabaseSchemaResult(_databaseFactory.SqlContext.SqlSyntax); if (_databaseSchemaValidationResult != null) @@ -513,7 +513,7 @@ namespace Umbraco.Core.Migrations.Install private Attempt CheckReadyForInstall() { - if (_databaseFactory.Configured == false) + if (_databaseFactory.CanConnect == false) { return Attempt.Fail(new Result { diff --git a/src/Umbraco.Core/Persistence/IUmbracoDatabaseFactory.cs b/src/Umbraco.Core/Persistence/IUmbracoDatabaseFactory.cs index 0236fc4bd5..c2d65b824f 100644 --- a/src/Umbraco.Core/Persistence/IUmbracoDatabaseFactory.cs +++ b/src/Umbraco.Core/Persistence/IUmbracoDatabaseFactory.cs @@ -10,22 +10,35 @@ namespace Umbraco.Core.Persistence /// /// Creates a new database. /// - /// The new database must be disposed after being used. + /// + /// The new database must be disposed after being used. + /// Creating a database causes the factory to initialize if it is not already initialized. + /// IUmbracoDatabase CreateDatabase(); /// - /// Gets a value indicating whether the database factory is configured. + /// Gets a value indicating whether the database factory is configured, i.e. whether + /// its connection string and provider name have been set. The factory may however not + /// be initialized (see ). /// bool Configured { get; } + /// + /// Gets a value indicating whether the database factory is initialized, i.e. whether + /// its internal state is ready and it has been possible to connect to the database. + /// + bool Initialized { get; } + /// /// Gets the connection string. /// - /// Throws if the factory is not configured. + /// May return null if the database factory is not configured. string ConnectionString { get; } /// - /// Gets a value indicating whether the database can connect. + /// Gets a value indicating whether the database factory is configured (see ), + /// and it is possible to connect to the database. The factory may however not be initialized (see + /// ). /// bool CanConnect { get; } @@ -37,6 +50,9 @@ namespace Umbraco.Core.Persistence /// /// Gets the Sql context. /// + /// + /// Getting the Sql context causes the factory to initialize if it is not already initialized. + /// ISqlContext SqlContext { get; } /// diff --git a/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs b/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs index dc86ff060c..13422f43b1 100644 --- a/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs +++ b/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs @@ -28,7 +28,8 @@ namespace Umbraco.Core.Persistence { private readonly Lazy _mappers; private readonly ILogger _logger; - private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); + + private object _lock = new object(); private DatabaseFactory _npocoDatabaseFactory; private IPocoDataFactory _pocoDataFactory; @@ -36,12 +37,13 @@ namespace Umbraco.Core.Persistence private string _providerName; private DbProviderFactory _dbProviderFactory; private DatabaseType _databaseType; - private bool _serverVersionDetected; private ISqlSyntaxProvider _sqlSyntax; private RetryPolicy _connectionRetryPolicy; private RetryPolicy _commandRetryPolicy; private NPoco.MapperCollection _pocoMappers; + private SqlContext _sqlContext; private bool _upgrading; + private bool _initialized; #region Constructors @@ -106,36 +108,30 @@ namespace Umbraco.Core.Persistence #endregion /// - public bool Configured { get; private set; } - - /// - public string ConnectionString + public bool Configured { get { - EnsureConfigured(); - return _connectionString; + lock (_lock) + { + return !_connectionString.IsNullOrWhiteSpace() && !_providerName.IsNullOrWhiteSpace(); + } } } /// - public bool CanConnect - { - get - { - if (!Configured || !DbConnectionExtensions.IsConnectionAvailable(_connectionString, _providerName)) return false; + public bool Initialized => Volatile.Read(ref _initialized); - if (_serverVersionDetected) return true; + /// + public string ConnectionString => _connectionString; - if (_databaseType.IsSqlServer()) - DetectSqlServerVersion(); - _serverVersionDetected = true; + /// + public bool CanConnect => + // actually tries to connect to the database (regardless of configured/initialized) + !_connectionString.IsNullOrWhiteSpace() && !_providerName.IsNullOrWhiteSpace() && + DbConnectionExtensions.IsConnectionAvailable(_connectionString, _providerName); - return true; - } - } - - private void DetectSqlServerVersion() + private void UpdateSqlServerDatabaseType() { // replace NPoco database type by a more efficient one @@ -171,7 +167,15 @@ namespace Umbraco.Core.Persistence } /// - public ISqlContext SqlContext { get; private set; } + public ISqlContext SqlContext + { + get + { + // must be initialized to have a context + EnsureInitialized(); + return _sqlContext; + } + } /// public void ConfigureForUpgrade() @@ -182,63 +186,79 @@ namespace Umbraco.Core.Persistence /// public void Configure(string connectionString, string providerName) { - try + if (connectionString.IsNullOrWhiteSpace()) throw new ArgumentNullException(nameof(connectionString)); + if (providerName.IsNullOrWhiteSpace()) throw new ArgumentNullException(nameof(providerName)); + + lock (_lock) { - _lock.EnterWriteLock(); - - _logger.Debug("Configuring."); - - if (Configured) throw new InvalidOperationException("Already configured."); - - if (connectionString.IsNullOrWhiteSpace()) throw new ArgumentNullException(nameof(connectionString)); - if (providerName.IsNullOrWhiteSpace()) throw new ArgumentNullException(nameof(providerName)); + if (Volatile.Read(ref _initialized)) + throw new InvalidOperationException("Already initialized."); _connectionString = connectionString; _providerName = providerName; - - _connectionRetryPolicy = RetryPolicyFactory.GetDefaultSqlConnectionRetryPolicyByConnectionString(_connectionString); - _commandRetryPolicy = RetryPolicyFactory.GetDefaultSqlCommandRetryPolicyByConnectionString(_connectionString); - - _dbProviderFactory = DbProviderFactories.GetFactory(_providerName); - if (_dbProviderFactory == null) - throw new Exception($"Can't find a provider factory for provider name \"{_providerName}\"."); - _databaseType = DatabaseType.Resolve(_dbProviderFactory.GetType().Name, _providerName); - if (_databaseType == null) - throw new Exception($"Can't find an NPoco database type for provider name \"{_providerName}\"."); - - _sqlSyntax = GetSqlSyntaxProvider(_providerName); - if (_sqlSyntax == null) - throw new Exception($"Can't find a sql syntax provider for provider name \"{_providerName}\"."); - - // ensure we have only 1 set of mappers, and 1 PocoDataFactory, for all database - // so that everything NPoco is properly cached for the lifetime of the application - _pocoMappers = new NPoco.MapperCollection { new PocoMapper() }; - var factory = new FluentPocoDataFactory(GetPocoDataFactoryResolver); - _pocoDataFactory = factory; - var config = new FluentConfig(xmappers => factory); - - // create the database factory - _npocoDatabaseFactory = DatabaseFactory.Config(x => x - .UsingDatabase(CreateDatabaseInstance) // creating UmbracoDatabase instances - .WithFluentConfig(config)); // with proper configuration - - if (_npocoDatabaseFactory == null) throw new NullReferenceException("The call to UmbracoDatabaseFactory.Config yielded a null UmbracoDatabaseFactory instance."); - - SqlContext = new SqlContext(_sqlSyntax, _databaseType, _pocoDataFactory, _mappers); - - _logger.Debug("Configured."); - Configured = true; - } - finally - { - if (_lock.IsWriteLockHeld) - _lock.ExitWriteLock(); } + + // rest to be lazy-initialized + } + + private void EnsureInitialized() + { + LazyInitializer.EnsureInitialized(ref _sqlContext, ref _initialized, ref _lock, Initialize); + } + + private SqlContext Initialize() + { + _logger.Debug("Initializing."); + + if (_connectionString.IsNullOrWhiteSpace()) throw new InvalidOperationException("The factory has not been configured with a proper connection string."); + if (_providerName.IsNullOrWhiteSpace()) throw new InvalidOperationException("The factory has not been configured with a proper provider name."); + + // cannot initialize without being able to talk to the database + if (!DbConnectionExtensions.IsConnectionAvailable(_connectionString, _providerName)) + throw new Exception("Cannot connect to the database."); + + _connectionRetryPolicy = RetryPolicyFactory.GetDefaultSqlConnectionRetryPolicyByConnectionString(_connectionString); + _commandRetryPolicy = RetryPolicyFactory.GetDefaultSqlCommandRetryPolicyByConnectionString(_connectionString); + + _dbProviderFactory = DbProviderFactories.GetFactory(_providerName); + if (_dbProviderFactory == null) + throw new Exception($"Can't find a provider factory for provider name \"{_providerName}\"."); + _databaseType = DatabaseType.Resolve(_dbProviderFactory.GetType().Name, _providerName); + if (_databaseType == null) + throw new Exception($"Can't find an NPoco database type for provider name \"{_providerName}\"."); + + _sqlSyntax = GetSqlSyntaxProvider(_providerName); + if (_sqlSyntax == null) + throw new Exception($"Can't find a sql syntax provider for provider name \"{_providerName}\"."); + + if (_databaseType.IsSqlServer()) + UpdateSqlServerDatabaseType(); + + // ensure we have only 1 set of mappers, and 1 PocoDataFactory, for all database + // so that everything NPoco is properly cached for the lifetime of the application + _pocoMappers = new NPoco.MapperCollection { new PocoMapper() }; + var factory = new FluentPocoDataFactory(GetPocoDataFactoryResolver); + _pocoDataFactory = factory; + var config = new FluentConfig(xmappers => factory); + + // create the database factory + _npocoDatabaseFactory = DatabaseFactory.Config(x => x + .UsingDatabase(CreateDatabaseInstance) // creating UmbracoDatabase instances + .WithFluentConfig(config)); // with proper configuration + + if (_npocoDatabaseFactory == null) + throw new NullReferenceException("The call to UmbracoDatabaseFactory.Config yielded a null UmbracoDatabaseFactory instance."); + + _logger.Debug("Initialized."); + + return new SqlContext(_sqlSyntax, _databaseType, _pocoDataFactory, _mappers); } /// public IUmbracoDatabase CreateDatabase() { + // must be initialized to create a database + EnsureInitialized(); return (IUmbracoDatabase) _npocoDatabaseFactory.GetDatabase(); } @@ -260,22 +280,6 @@ namespace Umbraco.Core.Persistence } } - // ensures that the database is configured, else throws - private void EnsureConfigured() - { - _lock.EnterReadLock(); - try - { - if (Configured == false) - throw new InvalidOperationException("Not configured."); - } - finally - { - if (_lock.IsReadLockHeld) - _lock.ExitReadLock(); - } - } - // method used by NPoco's UmbracoDatabaseFactory to actually create the database instance private UmbracoDatabase CreateDatabaseInstance() { @@ -292,7 +296,7 @@ namespace Umbraco.Core.Persistence //var db = _umbracoDatabaseAccessor.UmbracoDatabase; //_umbracoDatabaseAccessor.UmbracoDatabase = null; //db?.Dispose(); - Configured = false; + Volatile.Write(ref _initialized, false); } // during tests, the thread static var can leak between tests diff --git a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs index c276dc35ca..fb451b1d5c 100644 --- a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs +++ b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs @@ -43,16 +43,6 @@ namespace Umbraco.Tests.Persistence _databaseFactory = null; } - [Test] - public void GetDatabaseType() - { - using (var database = _databaseFactory.CreateDatabase()) - { - var databaseType = database.DatabaseType; - Assert.AreEqual(DatabaseType.SQLCe, databaseType); - } - } - [Test] public void CreateDatabase() // FIXME: move to DatabaseBuilderTest! { @@ -79,6 +69,13 @@ namespace Umbraco.Tests.Persistence // re-create the database factory and database context with proper connection string _databaseFactory = new UmbracoDatabaseFactory(connString, Constants.DbProviderNames.SqlCe, _logger, new Lazy(() => Mock.Of())); + // test get database type (requires an actual database) + using (var database = _databaseFactory.CreateDatabase()) + { + var databaseType = database.DatabaseType; + Assert.AreEqual(DatabaseType.SQLCe, databaseType); + } + // create application context //var appCtx = new ApplicationContext( // _databaseFactory, From 89670617582b7117e3119eb02c6f30f59661bbf5 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 5 Jun 2019 15:21:00 +1000 Subject: [PATCH 03/10] fixes semi colons --- .../src/views/propertyeditors/rte/rte.controller.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js index 5bcd3b9330..3f762007a0 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js @@ -42,8 +42,8 @@ angular.module("umbraco") var standardConfig = result[promises.length - 1]; - var width = parseInt(editorConfig.dimensions.width, 10) || null - var height = parseInt(editorConfig.dimensions.height, 10) || null + var width = parseInt(editorConfig.dimensions.width, 10) || null; + var height = parseInt(editorConfig.dimensions.height, 10) || null; if (height !== null) { standardConfig.plugins.splice(standardConfig.plugins.indexOf("autoresize"), 1); From 49c76c744e3e13f752bae5f6baed7de5a5633a10 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 5 Jun 2019 16:06:55 +1000 Subject: [PATCH 04/10] Fixes width/height for when in distraction free mode --- .../src/views/propertyeditors/rte/rte.controller.js | 10 +++++++--- .../src/views/propertyeditors/rte/rte.html | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js index 3f762007a0..d1fedf7db6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js @@ -20,6 +20,13 @@ angular.module("umbraco") editorConfig.maxImageSize = tinyMceService.defaultPrevalues().maxImageSize; } + var width = parseInt(editorConfig.dimensions.width, 10) || null; + var height = parseInt(editorConfig.dimensions.height, 10) || null; + + $scope.containerWidth = editorConfig.mode === "distraction-free" ? (width ? width : "auto") : "auto"; + $scope.containerHeight = editorConfig.mode === "distraction-free" ? (height ? height : "auto") : "auto"; + $scope.containerOverflow = editorConfig.mode === "distraction-free" ? (height ? "auto" : "inherit") : "inherit"; + var promises = []; //queue file loading @@ -42,9 +49,6 @@ angular.module("umbraco") var standardConfig = result[promises.length - 1]; - var width = parseInt(editorConfig.dimensions.width, 10) || null; - var height = parseInt(editorConfig.dimensions.height, 10) || null; - if (height !== null) { standardConfig.plugins.splice(standardConfig.plugins.indexOf("autoresize"), 1); } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.html index a68bfe978e..7dde17bb06 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.html @@ -1,6 +1,6 @@
-
From 3d2379d5823b13bc0705cccf6dcf4ad2f95ae826 Mon Sep 17 00:00:00 2001 From: "Maarten v.d. Donk" Date: Wed, 5 Jun 2019 11:34:42 +0200 Subject: [PATCH 05/10] Correct location for Visual Studio xml documentation files (5588) --- build/NuSpecs/UmbracoCms.Core.nuspec | 2 +- build/NuSpecs/UmbracoCms.Web.nuspec | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/NuSpecs/UmbracoCms.Core.nuspec b/build/NuSpecs/UmbracoCms.Core.nuspec index f3f8f47b57..56462fcc40 100644 --- a/build/NuSpecs/UmbracoCms.Core.nuspec +++ b/build/NuSpecs/UmbracoCms.Core.nuspec @@ -52,7 +52,7 @@ - + diff --git a/build/NuSpecs/UmbracoCms.Web.nuspec b/build/NuSpecs/UmbracoCms.Web.nuspec index 3c8fed78f5..614a816f3f 100644 --- a/build/NuSpecs/UmbracoCms.Web.nuspec +++ b/build/NuSpecs/UmbracoCms.Web.nuspec @@ -53,9 +53,9 @@ - - - + + + From 1565ff1661d05a2f590edada1b63ec7642ea38a3 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Thu, 6 Jun 2019 08:04:06 +0200 Subject: [PATCH 06/10] Fix JS error when the RTE has unconfigured dimensions --- .../src/views/propertyeditors/rte/rte.controller.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js index d1fedf7db6..3ed5f49b92 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js @@ -20,8 +20,8 @@ angular.module("umbraco") editorConfig.maxImageSize = tinyMceService.defaultPrevalues().maxImageSize; } - var width = parseInt(editorConfig.dimensions.width, 10) || null; - var height = parseInt(editorConfig.dimensions.height, 10) || null; + var width = editorConfig.dimensions ? parseInt(editorConfig.dimensions.width, 10) || null : null; + var height = editorConfig.dimensions ? parseInt(editorConfig.dimensions.height, 10) || null : null; $scope.containerWidth = editorConfig.mode === "distraction-free" ? (width ? width : "auto") : "auto"; $scope.containerHeight = editorConfig.mode === "distraction-free" ? (height ? height : "auto") : "auto"; From 70fb48d94a0867f43883e4f85078815af6032af6 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Thu, 6 Jun 2019 08:39:21 +0200 Subject: [PATCH 07/10] Fix broken culture variance toggle on content type properties --- .../common/directives/components/umbgroupsbuilder.directive.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js index bbbdd392b2..396699866c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js @@ -505,6 +505,7 @@ property.showOnMemberProfile = propertyModel.showOnMemberProfile; property.memberCanEdit = propertyModel.memberCanEdit; property.isSensitiveValue = propertyModel.isSensitiveValue; + property.allowCultureVariant = propertyModel.allowCultureVariant; // update existing data types if(model.updateSameDataTypes) { From 096004db1351ca2eff58fdf3032630a52e5516d8 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 6 Jun 2019 22:34:57 +1000 Subject: [PATCH 08/10] fixes infinite loop issue --- .../Repositories/Implement/ContentTypeCommonRepository.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeCommonRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeCommonRepository.cs index 645ab9f924..ccafb9f771 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeCommonRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeCommonRepository.cs @@ -140,10 +140,10 @@ namespace Umbraco.Core.Persistence.Repositories.Implement while (templateDtoIx < templateDtos.Count && templateDtos[templateDtoIx].ContentTypeNodeId == contentType.Id) { var allowedDto = templateDtos[templateDtoIx]; + templateDtoIx++; if (!templates.TryGetValue(allowedDto.TemplateNodeId, out var template)) continue; allowedTemplates.Add(template); - templateDtoIx++; - + if (allowedDto.IsDefault) defaultTemplateId = template.Id; } From 87b3fb55395ee979be67139387d8c1e7a3eef09c Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 7 Jun 2019 10:18:45 +1000 Subject: [PATCH 09/10] Fixes BulkInsertRecordsSqlServer --- src/Umbraco.Core/Persistence/NPocoDatabaseExtensions-Bulk.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Umbraco.Core/Persistence/NPocoDatabaseExtensions-Bulk.cs b/src/Umbraco.Core/Persistence/NPocoDatabaseExtensions-Bulk.cs index c9d85feb25..c6ad4574cd 100644 --- a/src/Umbraco.Core/Persistence/NPocoDatabaseExtensions-Bulk.cs +++ b/src/Umbraco.Core/Persistence/NPocoDatabaseExtensions-Bulk.cs @@ -232,6 +232,11 @@ namespace Umbraco.Core.Persistence using (var copy = new SqlBulkCopy(tConnection, SqlBulkCopyOptions.Default, tTransaction) { BulkCopyTimeout = 10000, DestinationTableName = tableName }) using (var bulkReader = new PocoDataDataReader(records, pocoData, syntax)) { + foreach(var col in bulkReader.ColumnMappings) + { + copy.ColumnMappings.Add(col.DestinationColumn, col.DestinationColumn); + } + copy.WriteToServer(bulkReader); return bulkReader.RecordsAffected; } From 5ca9600c9805c9993a7e1e798938f53d1d9bf927 Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 7 Jun 2019 11:01:30 +1000 Subject: [PATCH 10/10] adds comments --- src/Umbraco.Core/Persistence/NPocoDatabaseExtensions-Bulk.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Umbraco.Core/Persistence/NPocoDatabaseExtensions-Bulk.cs b/src/Umbraco.Core/Persistence/NPocoDatabaseExtensions-Bulk.cs index c6ad4574cd..0574e37c4c 100644 --- a/src/Umbraco.Core/Persistence/NPocoDatabaseExtensions-Bulk.cs +++ b/src/Umbraco.Core/Persistence/NPocoDatabaseExtensions-Bulk.cs @@ -232,6 +232,9 @@ namespace Umbraco.Core.Persistence using (var copy = new SqlBulkCopy(tConnection, SqlBulkCopyOptions.Default, tTransaction) { BulkCopyTimeout = 10000, DestinationTableName = tableName }) using (var bulkReader = new PocoDataDataReader(records, pocoData, syntax)) { + //we need to add column mappings here because otherwise columns will be matched by their order and if the order of them are different in the DB compared + //to the order in which they are declared in the model then this will not work, so instead we will add column mappings by name so that this explicitly uses + //the names instead of their ordering. foreach(var col in bulkReader.ColumnMappings) { copy.ColumnMappings.Add(col.DestinationColumn, col.DestinationColumn);