diff --git a/src/Umbraco.Core/Models/PreValue.cs b/src/Umbraco.Core/Models/PreValue.cs
index d0bdcc6d11..92cada007a 100644
--- a/src/Umbraco.Core/Models/PreValue.cs
+++ b/src/Umbraco.Core/Models/PreValue.cs
@@ -19,7 +19,7 @@
///
/// The value stored for the pre-value field
///
- public string Value { get; private set; }
+ public string Value { get; set; }
///
/// The database id for the pre-value field value
diff --git a/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs
index 423802fbb5..31deac0e94 100644
--- a/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs
@@ -14,6 +14,7 @@ using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Services;
+using NullCacheProvider = Umbraco.Core.Persistence.Caching.NullCacheProvider;
namespace Umbraco.Core.Persistence.Repositories
{
@@ -23,17 +24,20 @@ namespace Umbraco.Core.Persistence.Repositories
internal class DataTypeDefinitionRepository : PetaPocoRepositoryBase, IDataTypeDefinitionRepository
{
private readonly CacheHelper _cacheHelper;
+ private DataTypePreValueRepository _preValRepository;
public DataTypeDefinitionRepository(IDatabaseUnitOfWork work, CacheHelper cacheHelper)
: base(work)
{
_cacheHelper = cacheHelper;
+ _preValRepository = new DataTypePreValueRepository(work, NullCacheProvider.Current);
}
public DataTypeDefinitionRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, CacheHelper cacheHelper)
: base(work, cache)
{
_cacheHelper = cacheHelper;
+ _preValRepository = new DataTypePreValueRepository(work, NullCacheProvider.Current);
}
private readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
@@ -126,6 +130,42 @@ namespace Umbraco.Core.Persistence.Repositories
#region Unit of Work Implementation
+ public override void PersistUpdatedItem(IEntity entity)
+ {
+ if (entity is PreValue)
+ {
+ _preValRepository.PersistUpdatedItem(entity);
+ }
+ else
+ {
+ base.PersistUpdatedItem(entity);
+ }
+ }
+
+ public override void PersistNewItem(IEntity entity)
+ {
+ if (entity is PreValue)
+ {
+ _preValRepository.PersistNewItem(entity);
+ }
+ else
+ {
+ base.PersistNewItem(entity);
+ }
+ }
+
+ public override void PersistDeletedItem(IEntity entity)
+ {
+ if (entity is PreValue)
+ {
+ _preValRepository.PersistDeletedItem(entity);
+ }
+ else
+ {
+ base.PersistDeletedItem(entity);
+ }
+ }
+
protected override void PersistNewItem(IDataTypeDefinition entity)
{
((DataTypeDefinition)entity).AddingEntity();
@@ -300,6 +340,82 @@ AND umbracoNode.id <> @id",
}
}
+ public void AddOrUpdatePreValues(int dataTypeId, IDictionary values)
+ {
+ var dtd = Get(dataTypeId);
+ if (dtd == null)
+ {
+ throw new InvalidOperationException("No data type found with id " + dataTypeId);
+ }
+ AddOrUpdatePreValues(dtd, values);
+ }
+
+ public void AddOrUpdatePreValues(IDataTypeDefinition dataType, IDictionary values)
+ {
+ var currentVals = new DataTypePreValueDto[]{};
+ if (dataType.HasIdentity)
+ {
+ //first just get all pre-values for this data type so we can compare them to see if we need to insert or update or replace
+ var sql = new Sql().Select("*")
+ .From()
+ .Where(dto => dto.DataTypeNodeId == dataType.Id)
+ .OrderBy(dto => dto.SortOrder);
+ currentVals = Database.Fetch(sql).ToArray();
+ }
+
+ //already existing, need to be updated
+ var valueIds = values.Where(x => x.Value.Id > 0).Select(x => x.Value.Id).ToArray();
+ var existingByIds = currentVals.Where(x => valueIds.Contains(x.Id)).ToArray();
+
+ //These ones need to be removed from the db, they no longer exist in the new values
+ var deleteById = currentVals.Where(x => valueIds.Contains(x.Id) == false);
+
+ foreach (var d in deleteById)
+ {
+ _preValRepository.Delete(new PreValueEntity
+ {
+ Alias = d.Alias,
+ Id = d.Id,
+ Value = d.Value,
+ DataType = dataType,
+ SortOrder = d.SortOrder
+ });
+ }
+
+ var sortOrder = 1;
+
+ foreach (var pre in values)
+ {
+ var existing = existingByIds.FirstOrDefault(valueDto => valueDto.Id == pre.Value.Id);
+ if (existing != null)
+ {
+ existing.Value = pre.Value.Value;
+ existing.SortOrder = sortOrder;
+ _preValRepository.AddOrUpdate(new PreValueEntity
+ {
+ Alias = existing.Alias,
+ Id = existing.Id,
+ SortOrder = existing.SortOrder,
+ Value = existing.Value,
+ DataType = dataType,
+ });
+ }
+ else
+ {
+ _preValRepository.AddOrUpdate(new PreValueEntity
+ {
+ Alias = pre.Key,
+ SortOrder = sortOrder,
+ Value = pre.Value.Value,
+ DataType = dataType,
+ });
+ }
+
+ sortOrder++;
+ }
+
+ }
+
private string GetPrefixedCacheKey(int dataTypeId)
{
return CacheKeys.DataTypePreValuesCacheKey + dataTypeId + "-";
@@ -327,5 +443,129 @@ AND umbracoNode.id <> @id",
return collection;
}
+
+ ///
+ /// Private class to handle pre-value crud based on units of work with transactions
+ ///
+ public class PreValueEntity : Entity, IAggregateRoot
+ {
+ public string Value { get; set; }
+ public string Alias { get; set; }
+ public IDataTypeDefinition DataType { get; set; }
+ public int SortOrder { get; set; }
+ }
+
+ ///
+ /// Private class to handle pre-value crud based on standard principles and units of work with transactions
+ ///
+ private class DataTypePreValueRepository : PetaPocoRepositoryBase
+ {
+ public DataTypePreValueRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) : base(work, cache)
+ {
+ }
+
+ #region Not implemented (don't need to for the purposes of this repo)
+ protected override PreValueEntity PerformGet(int id)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override IEnumerable PerformGetAll(params int[] ids)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override IEnumerable PerformGetByQuery(IQuery query)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override Sql GetBaseQuery(bool isCount)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override string GetBaseWhereClause()
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override IEnumerable GetDeleteClauses()
+ {
+ return new List();
+ }
+
+ protected override Guid NodeObjectTypeId
+ {
+ get { throw new NotImplementedException(); }
+ }
+ #endregion
+
+ protected override void PersistDeletedItem(PreValueEntity entity)
+ {
+ Database.Execute(
+ "DELETE FROM cmsDataTypePreValues WHERE id=@Id",
+ new { Id = entity.Id });
+ }
+
+ protected override void PersistNewItem(PreValueEntity entity)
+ {
+ if (entity.DataType.HasIdentity == false)
+ {
+ throw new InvalidOperationException("Cannot insert a pre value for a data type that has no identity");
+ }
+
+ //Cannot add a duplicate alias
+ var exists = Database.ExecuteScalar(@"SELECT COUNT(*) FROM cmsDataTypePreValues
+WHERE alias = @alias
+AND datatypeNodeId = @dtdid",
+ new { alias = entity.Alias, dtdid = entity.DataType.Id });
+ if (exists > 0)
+ {
+ throw new DuplicateNameException("A pre value with the alias " + entity.Alias + " already exists for this data type");
+ }
+
+ var dto = new DataTypePreValueDto
+ {
+ DataTypeNodeId = entity.DataType.Id,
+ Value = entity.Value,
+ SortOrder = entity.SortOrder,
+ Alias = entity.Alias
+ };
+ Database.Insert(dto);
+ }
+
+ protected override void PersistUpdatedItem(PreValueEntity entity)
+ {
+ if (entity.DataType.HasIdentity == false)
+ {
+ throw new InvalidOperationException("Cannot update a pre value for a data type that has no identity");
+ }
+
+ //Cannot change to a duplicate alias
+ var exists = Database.ExecuteScalar(@"SELECT COUNT(*) FROM cmsDataTypePreValues
+WHERE alias = @alias
+AND datatypeNodeId = @dtdid
+AND id <> @id",
+ new { id = entity.Id, alias = entity.Alias, dtdid = entity.DataType.Id });
+ if (exists > 0)
+ {
+ throw new DuplicateNameException("A pre value with the alias " + entity.Alias + " already exists for this data type");
+ }
+
+ var dto = new DataTypePreValueDto
+ {
+ DataTypeNodeId = entity.DataType.Id,
+ Id = entity.Id,
+ Value = entity.Value,
+ SortOrder = entity.SortOrder,
+ Alias = entity.Alias
+ };
+ Database.Update(dto);
+ }
+ }
+
}
+
+
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IDataTypeDefinitionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IDataTypeDefinitionRepository.cs
index 77fe5edc89..f04b90c2e0 100644
--- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IDataTypeDefinitionRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IDataTypeDefinitionRepository.cs
@@ -1,4 +1,6 @@
-using Umbraco.Core.Models;
+using System.Collections.Generic;
+using Umbraco.Core.Models;
+using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Persistence.Repositories
{
@@ -6,5 +8,8 @@ namespace Umbraco.Core.Persistence.Repositories
{
PreValueCollection GetPreValuesCollectionByDataTypeId(int dataTypeId);
string GetPreValueAsString(int preValueId);
+
+ void AddOrUpdatePreValues(IDataTypeDefinition dataType, IDictionary values);
+ void AddOrUpdatePreValues(int dataTypeId, IDictionary values);
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Services/DataTypeService.cs b/src/Umbraco.Core/Services/DataTypeService.cs
index 45bb7016ef..78a340913e 100644
--- a/src/Umbraco.Core/Services/DataTypeService.cs
+++ b/src/Umbraco.Core/Services/DataTypeService.cs
@@ -153,17 +153,14 @@ namespace Umbraco.Core.Services
if (Saving.IsRaisedEventCancelled(new SaveEventArgs(dataTypeDefinition), this))
return;
- using (new WriteLock(Locker))
+ var uow = _uowProvider.GetUnitOfWork();
+ using (var repository = _repositoryFactory.CreateDataTypeDefinitionRepository(uow))
{
- var uow = _uowProvider.GetUnitOfWork();
- using (var repository = _repositoryFactory.CreateDataTypeDefinitionRepository(uow))
- {
- dataTypeDefinition.CreatorId = userId;
- repository.AddOrUpdate(dataTypeDefinition);
- uow.Commit();
+ dataTypeDefinition.CreatorId = userId;
+ repository.AddOrUpdate(dataTypeDefinition);
+ uow.Commit();
- Saved.RaiseEvent(new SaveEventArgs(dataTypeDefinition, false), this);
- }
+ Saved.RaiseEvent(new SaveEventArgs(dataTypeDefinition, false), this);
}
Audit.Add(AuditTypes.Save, string.Format("Save DataTypeDefinition performed by user"), userId, dataTypeDefinition.Id);
@@ -179,31 +176,29 @@ namespace Umbraco.Core.Services
if (Saving.IsRaisedEventCancelled(new SaveEventArgs(dataTypeDefinitions), this))
return;
- using (new WriteLock(Locker))
+ var uow = _uowProvider.GetUnitOfWork();
+ using (var repository = _repositoryFactory.CreateDataTypeDefinitionRepository(uow))
{
- var uow = _uowProvider.GetUnitOfWork();
- using (var repository = _repositoryFactory.CreateDataTypeDefinitionRepository(uow))
+ foreach (var dataTypeDefinition in dataTypeDefinitions)
{
- foreach (var dataTypeDefinition in dataTypeDefinitions)
- {
- dataTypeDefinition.CreatorId = userId;
- repository.AddOrUpdate(dataTypeDefinition);
- }
- uow.Commit();
-
- Saved.RaiseEvent(new SaveEventArgs(dataTypeDefinitions, false), this);
+ dataTypeDefinition.CreatorId = userId;
+ repository.AddOrUpdate(dataTypeDefinition);
}
+ uow.Commit();
+
+ Saved.RaiseEvent(new SaveEventArgs(dataTypeDefinitions, false), this);
}
+
Audit.Add(AuditTypes.Save, string.Format("Save DataTypeDefinition performed by user"), userId, -1);
}
///
/// Saves a list of PreValues for a given DataTypeDefinition
///
- /// Id of the DataTypeDefinition to save PreValues for
+ /// Id of the DataTypeDefinition to save PreValues for
/// List of string values to save
[Obsolete("This should no longer be used, use the alternative SavePreValues or SaveDataTypeAndPreValues methods instead. This will only insert pre-values without keys")]
- public void SavePreValues(int id, IEnumerable values)
+ public void SavePreValues(int dataTypeId, IEnumerable values)
{
//TODO: Should we raise an event here since we are really saving values for the data type?
@@ -215,7 +210,7 @@ namespace Umbraco.Core.Services
{
var sortOrderObj =
uow.Database.ExecuteScalar