Files
Umbraco-CMS/src/Umbraco.Core/Services/Implement/KeyValueService.cs

162 lines
5.6 KiB
C#
Raw Normal View History

2017-12-22 12:29:56 +01:00
using System;
using System.Linq;
using Umbraco.Core.Logging;
using Umbraco.Core.Migrations;
using Umbraco.Core.Migrations.Expressions.Create;
using Umbraco.Core.Scoping;
using Umbraco.Core.Persistence;
2017-12-28 09:06:33 +01:00
using Umbraco.Core.Persistence.Dtos;
2017-12-22 12:29:56 +01:00
namespace Umbraco.Core.Services.Implement
{
internal class KeyValueService : IKeyValueService
{
private readonly object _initialock = new object();
private readonly IScopeProvider _scopeProvider;
private readonly ILogger _logger;
private bool _initialized;
public KeyValueService(IScopeProvider scopeProvider, ILogger logger)
{
_scopeProvider = scopeProvider;
_logger = logger;
}
private void EnsureInitialized()
{
lock (_initialock)
{
if (_initialized) return;
Initialize();
_initialized = true;
}
}
private void Initialize()
{
2017-12-26 11:35:21 +01:00
// all this cannot be achieved via migrations since it needs to run
// before any migration, in order to figure out migrations
2017-12-22 12:29:56 +01:00
using (var scope = _scopeProvider.CreateScope())
{
2018-03-21 11:32:07 +01:00
// assume that if the lock object for key/value exists, then everything is ok
2017-12-26 11:35:21 +01:00
if (scope.Database.Exists<LockDto>(Constants.Locks.KeyValues))
2017-12-22 12:29:56 +01:00
{
2017-12-26 11:35:21 +01:00
scope.Complete();
return;
2017-12-22 12:29:56 +01:00
}
2018-03-21 11:32:07 +01:00
// drop the 'identity' on umbracoLock primary key
2017-12-26 11:35:21 +01:00
foreach (var sql in new[]
{
2018-03-21 11:32:07 +01:00
// create a temp. id column and copy values
2017-12-26 11:35:21 +01:00
"alter table umbracoLock add column nid int null;",
"update umbracoLock set nid = id;",
2018-03-21 11:32:07 +01:00
// drop the id column entirely (cannot just drop identity)
2017-12-26 11:35:21 +01:00
"alter table umbracoLock drop constraint PK_umbracoLock;",
"alter table umbracoLock drop column id;",
2018-03-21 11:32:07 +01:00
// recreate the id column without identity and copy values
2017-12-26 11:35:21 +01:00
"alter table umbracoLock add column id int null;",
"update umbracoLock set id = nid;",
2018-03-21 11:32:07 +01:00
// drop the temp. id column
2017-12-26 11:35:21 +01:00
"alter table umbracoLock drop column nid;",
2018-03-21 11:32:07 +01:00
// complete the primary key
2017-12-26 11:35:21 +01:00
"alter table umbracoLock alter column id int not null;",
"alter table umbracoLock add constraint PK_umbracoLock primary key (id);"
})
scope.Database.Execute(sql);
// insert the key-value lock
scope.Database.Execute($@"INSERT {scope.SqlContext.SqlSyntax.GetQuotedTableName(Constants.DatabaseSchema.Tables.Lock)} (id, name, value)
VALUES ({Constants.Locks.KeyValues}, 'KeyValues', 1);");
// create the key-value table
var context = new MigrationContext(scope.Database, _logger);
new CreateBuilder(context).Table<KeyValueDto>().Do();
2017-12-22 12:29:56 +01:00
scope.Complete();
}
}
2018-03-21 11:32:07 +01:00
/// <inheritdoc />
2017-12-22 12:29:56 +01:00
public string GetValue(string key)
{
EnsureInitialized();
using (var scope = _scopeProvider.CreateScope())
{
var sql = scope.SqlContext.Sql().Select<KeyValueDto>().From<KeyValueDto>().Where<KeyValueDto>(x => x.Key == key);
var dto = scope.Database.Fetch<KeyValueDto>(sql).FirstOrDefault();
scope.Complete();
return dto?.Value;
}
}
2018-03-21 11:32:07 +01:00
/// <inheritdoc />
2017-12-22 12:29:56 +01:00
public void SetValue(string key, string value)
{
EnsureInitialized();
using (var scope = _scopeProvider.CreateScope())
{
scope.WriteLock(Constants.Locks.KeyValues);
var sql = scope.SqlContext.Sql().Select<KeyValueDto>().From<KeyValueDto>().Where<KeyValueDto>(x => x.Key == key);
var dto = scope.Database.Fetch<KeyValueDto>(sql).FirstOrDefault();
if (dto == null)
{
dto = new KeyValueDto
{
Key = key,
Value = value,
Updated = DateTime.Now
};
scope.Database.Insert(dto);
}
else
{
dto.Value = value;
dto.Updated = DateTime.Now;
scope.Database.Update(dto);
}
scope.Complete();
}
}
2018-03-21 11:32:07 +01:00
/// <inheritdoc />
2017-12-22 12:29:56 +01:00
public void SetValue(string key, string originValue, string newValue)
2018-03-21 11:32:07 +01:00
{
if (!TrySetValue(key, originValue, newValue))
throw new InvalidOperationException("Could not set the value.");
}
/// <inheritdoc />
public bool TrySetValue(string key, string originValue, string newValue)
2017-12-22 12:29:56 +01:00
{
EnsureInitialized();
using (var scope = _scopeProvider.CreateScope())
{
scope.WriteLock(Constants.Locks.KeyValues);
var sql = scope.SqlContext.Sql().Select<KeyValueDto>().From<KeyValueDto>().Where<KeyValueDto>(x => x.Key == key);
var dto = scope.Database.Fetch<KeyValueDto>(sql).FirstOrDefault();
2018-03-21 11:32:07 +01:00
if (dto == null || dto.Value != originValue)
return false;
2017-12-22 12:29:56 +01:00
dto.Value = newValue;
dto.Updated = DateTime.Now;
scope.Database.Update(dto);
scope.Complete();
}
2018-03-21 11:32:07 +01:00
return true;
2017-12-22 12:29:56 +01:00
}
}
}