Refactoring Unit Of Work, adding TransactionTypes and a new Repository structure.
Adding new Factory structure. Related to U4-973, U4-955 and U4-979
This commit is contained in:
47
src/Umbraco.Core/Persistence/DatabaseFactory.cs
Normal file
47
src/Umbraco.Core/Persistence/DatabaseFactory.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Persistence
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to the PetaPoco database as Singleton, so the database is created once in app lifecycle.
|
||||
/// This is necessary for transactions to work properly
|
||||
/// </summary>
|
||||
public sealed class DatabaseFactory
|
||||
{
|
||||
#region Singleton
|
||||
|
||||
private static Database _database;
|
||||
private static volatile DatabaseFactory _instance;
|
||||
private static readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim();
|
||||
|
||||
private DatabaseFactory() { }
|
||||
|
||||
public static DatabaseFactory Current
|
||||
{
|
||||
get
|
||||
{
|
||||
using (new WriteLock(Lock))
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new DatabaseFactory();
|
||||
_database = new Database(GlobalSettings.DbDsn);
|
||||
}
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Returns an instance of the PetaPoco database
|
||||
/// </summary>
|
||||
public Database Database
|
||||
{
|
||||
get { return _database; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Factories
|
||||
{
|
||||
internal class ContentFactory
|
||||
{
|
||||
internal static Content CreateContent(int key, IContentType contentType, DocumentDto documentDto, IEnumerable<PropertyDataDto> propertyDataDtos)
|
||||
{
|
||||
var properties = new List<Property>();
|
||||
foreach (var dto in propertyDataDtos)
|
||||
{
|
||||
var propertyType =
|
||||
contentType.CompositionPropertyTypes.FirstOrDefault(x => x.Id == dto.PropertyTypeId);
|
||||
properties.Add(propertyType.CreatePropertyFromRawValue(dto.GetValue));
|
||||
}
|
||||
|
||||
return new Content(documentDto.ContentVersionDto.ContentDto.NodeDto.ParentId, contentType)
|
||||
{
|
||||
Id = key,
|
||||
Key = documentDto.ContentVersionDto.ContentDto.NodeDto.UniqueId.HasValue ? documentDto.ContentVersionDto.ContentDto.NodeDto.UniqueId.Value : key.ToGuid(),
|
||||
Name = documentDto.ContentVersionDto.ContentDto.NodeDto.Text,
|
||||
Path = documentDto.ContentVersionDto.ContentDto.NodeDto.Path,
|
||||
UserId = documentDto.ContentVersionDto.ContentDto.NodeDto.UserId.HasValue ? documentDto.ContentVersionDto.ContentDto.NodeDto.UserId.Value : documentDto.UserId,
|
||||
Level = documentDto.ContentVersionDto.ContentDto.NodeDto.Level,
|
||||
ParentId = documentDto.ContentVersionDto.ContentDto.NodeDto.ParentId,
|
||||
SortOrder = documentDto.ContentVersionDto.ContentDto.NodeDto.SortOrder,
|
||||
Trashed = documentDto.ContentVersionDto.ContentDto.NodeDto.Trashed,
|
||||
Published = documentDto.Published,
|
||||
CreateDate = documentDto.ContentVersionDto.ContentDto.NodeDto.CreateDate,
|
||||
UpdateDate = documentDto.ContentVersionDto.VersionDate,
|
||||
ExpireDate = documentDto.ExpiresDate,
|
||||
ReleaseDate = documentDto.ReleaseDate,
|
||||
Version = documentDto.ContentVersionDto.VersionId,
|
||||
Properties = new PropertyCollection(properties)
|
||||
};
|
||||
}
|
||||
|
||||
internal static NodeDto CreateNodeDto(IContent entity, string nodeObjectType)
|
||||
{
|
||||
var nodeDto = new NodeDto
|
||||
{
|
||||
CreateDate = entity.CreateDate,
|
||||
NodeId = entity.Id,
|
||||
Level = short.Parse(entity.Level.ToString(CultureInfo.InvariantCulture)),
|
||||
NodeObjectType = new Guid(nodeObjectType),
|
||||
ParentId = entity.ParentId,
|
||||
Path = entity.Path,
|
||||
SortOrder = entity.SortOrder,
|
||||
Text = entity.Name,
|
||||
Trashed = entity.Trashed,
|
||||
UniqueId = entity.Key,
|
||||
UserId = entity.UserId
|
||||
};
|
||||
|
||||
return nodeDto;
|
||||
}
|
||||
|
||||
internal static NodeDto CreateNodeDto(IContent entity, string nodeObjectType, string path, int level, int sortOrder)
|
||||
{
|
||||
var nodeDto = new NodeDto
|
||||
{
|
||||
CreateDate = entity.CreateDate,
|
||||
NodeId = entity.Id,
|
||||
Level = short.Parse(level.ToString(CultureInfo.InvariantCulture)),
|
||||
NodeObjectType = new Guid(nodeObjectType),
|
||||
ParentId = entity.ParentId,
|
||||
Path = path,
|
||||
SortOrder = sortOrder,
|
||||
Text = entity.Name,
|
||||
Trashed = entity.Trashed,
|
||||
UniqueId = entity.Key,
|
||||
UserId = entity.UserId
|
||||
};
|
||||
|
||||
return nodeDto;
|
||||
}
|
||||
|
||||
internal static ContentDto CreateContentDto(IContent entity, int primaryKey = 0)
|
||||
{
|
||||
var contentDto = new ContentDto
|
||||
{
|
||||
NodeId = entity.Id,
|
||||
ContentType = entity.ContentTypeId
|
||||
};
|
||||
|
||||
if (primaryKey > 0)
|
||||
{
|
||||
contentDto.PrimaryKey = primaryKey;
|
||||
}
|
||||
|
||||
return contentDto;
|
||||
}
|
||||
|
||||
internal static ContentVersionDto CreateContentVersionDto(IContent entity)
|
||||
{
|
||||
var contentVersionDto = new ContentVersionDto
|
||||
{
|
||||
NodeId = entity.Id,
|
||||
VersionDate = entity.UpdateDate,
|
||||
VersionId = entity.Version
|
||||
};
|
||||
return contentVersionDto;
|
||||
}
|
||||
|
||||
internal static DocumentDto CreateDocumentDto(IContent entity)
|
||||
{
|
||||
//NOTE Currently doesn't add Alias and templateId (legacy stuff that eventually will go away)
|
||||
var documentDto = new DocumentDto
|
||||
{
|
||||
ExpiresDate = entity.ExpireDate,
|
||||
Newest = true,
|
||||
NodeId = entity.Id,
|
||||
Published = entity.Published,
|
||||
ReleaseDate = entity.ReleaseDate,
|
||||
Text = entity.Name,
|
||||
UpdateDate = entity.UpdateDate,
|
||||
UserId = entity.UserId,
|
||||
VersionId = entity.Version
|
||||
};
|
||||
return documentDto;
|
||||
}
|
||||
|
||||
internal static List<PropertyDataDto> CreateProperties(int id, Guid version, IEnumerable<Property> properties)
|
||||
{
|
||||
var propertyDataDtos = new List<PropertyDataDto>();
|
||||
/*var serviceStackSerializer = new ServiceStackXmlSerializer();
|
||||
var service = new SerializationService(serviceStackSerializer);*/
|
||||
|
||||
foreach (var property in properties)
|
||||
{
|
||||
var dto = new PropertyDataDto { NodeId = id, PropertyTypeId = property.PropertyTypeId, VersionId = version };
|
||||
//TODO Add complex (PropertyEditor) ValueModels to the Ntext/Nvarchar column as a serialized 'Object' (DataTypeDatabaseType.Object)
|
||||
/*if (property.Value is IEditorModel)
|
||||
{
|
||||
var result = service.ToStream(property.Value);
|
||||
dto.Text = result.ResultStream.ToJsonString();
|
||||
}*/
|
||||
if (property.DataTypeDatabaseType == DataTypeDatabaseType.Integer)
|
||||
{
|
||||
dto.Integer = int.Parse(property.Value.ToString());
|
||||
}
|
||||
else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Date)
|
||||
{
|
||||
dto.Date = DateTime.Parse(property.Value.ToString());
|
||||
}
|
||||
else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
dto.Text = property.Value.ToString();
|
||||
}
|
||||
else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Nvarchar)
|
||||
{
|
||||
dto.VarChar = property.Value.ToString();
|
||||
}
|
||||
|
||||
propertyDataDtos.Add(dto);
|
||||
}
|
||||
return propertyDataDtos;
|
||||
}
|
||||
}
|
||||
}
|
||||
127
src/Umbraco.Core/Persistence/Factories/EntityFactory.cs
Normal file
127
src/Umbraco.Core/Persistence/Factories/EntityFactory.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Factories
|
||||
{
|
||||
internal class EntityFactory : IEntityFactory<IContent, DocumentDto>
|
||||
{
|
||||
private readonly IContentType _contentType;
|
||||
private readonly Guid _nodeObjectTypeId;
|
||||
private readonly int _id;
|
||||
private int _primaryKey;
|
||||
|
||||
public EntityFactory(IContentType contentType, Guid nodeObjectTypeId, int id)
|
||||
{
|
||||
_contentType = contentType;
|
||||
_nodeObjectTypeId = nodeObjectTypeId;
|
||||
_id = id;
|
||||
}
|
||||
|
||||
#region Implementation of IEntityFactory<IContent,DocumentDto>
|
||||
|
||||
public IContent BuildEntity(DocumentDto dto)
|
||||
{
|
||||
return new Content(dto.ContentVersionDto.ContentDto.NodeDto.ParentId, _contentType)
|
||||
{
|
||||
Id = _id,
|
||||
Key =
|
||||
dto.ContentVersionDto.ContentDto.NodeDto.UniqueId.HasValue
|
||||
? dto.ContentVersionDto.ContentDto.NodeDto.UniqueId.Value
|
||||
: _id.ToGuid(),
|
||||
Name = dto.ContentVersionDto.ContentDto.NodeDto.Text,
|
||||
Path = dto.ContentVersionDto.ContentDto.NodeDto.Path,
|
||||
UserId =
|
||||
dto.ContentVersionDto.ContentDto.NodeDto.UserId.HasValue
|
||||
? dto.ContentVersionDto.ContentDto.NodeDto.UserId.Value
|
||||
: dto.UserId,
|
||||
Level = dto.ContentVersionDto.ContentDto.NodeDto.Level,
|
||||
ParentId = dto.ContentVersionDto.ContentDto.NodeDto.ParentId,
|
||||
SortOrder = dto.ContentVersionDto.ContentDto.NodeDto.SortOrder,
|
||||
Trashed = dto.ContentVersionDto.ContentDto.NodeDto.Trashed,
|
||||
Published = dto.Published,
|
||||
CreateDate = dto.ContentVersionDto.ContentDto.NodeDto.CreateDate,
|
||||
UpdateDate = dto.ContentVersionDto.VersionDate,
|
||||
ExpireDate = dto.ExpiresDate,
|
||||
ReleaseDate = dto.ReleaseDate,
|
||||
Version = dto.ContentVersionDto.VersionId
|
||||
};
|
||||
}
|
||||
|
||||
public DocumentDto BuildDto(IContent entity)
|
||||
{
|
||||
//NOTE Currently doesn't add Alias and templateId (legacy stuff that eventually will go away)
|
||||
var documentDto = new DocumentDto
|
||||
{
|
||||
ExpiresDate = entity.ExpireDate,
|
||||
Newest = true,
|
||||
NodeId = entity.Id,
|
||||
Published = entity.Published,
|
||||
ReleaseDate = entity.ReleaseDate,
|
||||
Text = entity.Name,
|
||||
UpdateDate = entity.UpdateDate,
|
||||
UserId = entity.UserId,
|
||||
VersionId = entity.Version,
|
||||
ContentVersionDto = BuildContentVersionDto(entity)
|
||||
};
|
||||
return documentDto;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private ContentVersionDto BuildContentVersionDto(IContent entity)
|
||||
{
|
||||
var contentVersionDto = new ContentVersionDto
|
||||
{
|
||||
NodeId = entity.Id,
|
||||
VersionDate = entity.UpdateDate,
|
||||
VersionId = entity.Version,
|
||||
ContentDto = BuildContentDto(entity)
|
||||
};
|
||||
return contentVersionDto;
|
||||
}
|
||||
|
||||
private ContentDto BuildContentDto(IContent entity)
|
||||
{
|
||||
var contentDto = new ContentDto
|
||||
{
|
||||
NodeId = entity.Id,
|
||||
ContentType = entity.ContentTypeId,
|
||||
NodeDto = BuildNodeDto(entity)
|
||||
};
|
||||
|
||||
if (_primaryKey > 0)
|
||||
{
|
||||
contentDto.PrimaryKey = _primaryKey;
|
||||
}
|
||||
|
||||
return contentDto;
|
||||
}
|
||||
|
||||
private NodeDto BuildNodeDto(IContent entity)
|
||||
{
|
||||
var nodeDto = new NodeDto
|
||||
{
|
||||
CreateDate = entity.CreateDate,
|
||||
NodeId = entity.Id,
|
||||
Level = short.Parse(entity.Level.ToString(CultureInfo.InvariantCulture)),
|
||||
NodeObjectType = _nodeObjectTypeId,
|
||||
ParentId = entity.ParentId,
|
||||
Path = entity.Path,
|
||||
SortOrder = entity.SortOrder,
|
||||
Text = entity.Name,
|
||||
Trashed = entity.Trashed,
|
||||
UniqueId = entity.Key,
|
||||
UserId = entity.UserId
|
||||
};
|
||||
|
||||
return nodeDto;
|
||||
}
|
||||
|
||||
public void SetPrimaryKey(int primaryKey)
|
||||
{
|
||||
_primaryKey = primaryKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
src/Umbraco.Core/Persistence/Factories/IEntityFactory.cs
Normal file
12
src/Umbraco.Core/Persistence/Factories/IEntityFactory.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Factories
|
||||
{
|
||||
internal interface IEntityFactory<TEntity, TDto>
|
||||
where TEntity : class
|
||||
where TDto : class
|
||||
{
|
||||
TEntity BuildEntity(TDto dto);
|
||||
TDto BuildDto(TEntity entity);
|
||||
}
|
||||
}
|
||||
75
src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs
Normal file
75
src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Factories
|
||||
{
|
||||
internal class PropertyFactory : IEntityFactory<IEnumerable<Property>, IEnumerable<PropertyDataDto>>
|
||||
{
|
||||
private readonly IContentType _contentType;
|
||||
private readonly Guid _version;
|
||||
private readonly int _id;
|
||||
|
||||
#region Implementation of IEntityFactory<IContent,PropertyDataDto>
|
||||
|
||||
public PropertyFactory(IContentType contentType, Guid version, int id)
|
||||
{
|
||||
_contentType = contentType;
|
||||
_version = version;
|
||||
_id = id;
|
||||
}
|
||||
|
||||
public IEnumerable<Property> BuildEntity(IEnumerable<PropertyDataDto> dtos)
|
||||
{
|
||||
var properties = new List<Property>();
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
var propertyType =
|
||||
_contentType.CompositionPropertyTypes.FirstOrDefault(x => x.Id == dto.PropertyTypeId);
|
||||
properties.Add(propertyType.CreatePropertyFromRawValue(dto.GetValue));
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
public IEnumerable<PropertyDataDto> BuildDto(IEnumerable<Property> properties)
|
||||
{
|
||||
var propertyDataDtos = new List<PropertyDataDto>();
|
||||
/*var serviceStackSerializer = new ServiceStackXmlSerializer();
|
||||
var service = new SerializationService(serviceStackSerializer);*/
|
||||
|
||||
foreach (var property in properties)
|
||||
{
|
||||
var dto = new PropertyDataDto { NodeId = _id, PropertyTypeId = property.PropertyTypeId, VersionId = _version };
|
||||
//TODO Add complex (PropertyEditor) ValueModels to the Ntext/Nvarchar column as a serialized 'Object' (DataTypeDatabaseType.Object)
|
||||
/*if (property.Value is IEditorModel)
|
||||
{
|
||||
var result = service.ToStream(property.Value);
|
||||
dto.Text = result.ResultStream.ToJsonString();
|
||||
}*/
|
||||
if (property.DataTypeDatabaseType == DataTypeDatabaseType.Integer)
|
||||
{
|
||||
dto.Integer = int.Parse(property.Value.ToString());
|
||||
}
|
||||
else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Date)
|
||||
{
|
||||
dto.Date = DateTime.Parse(property.Value.ToString());
|
||||
}
|
||||
else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
dto.Text = property.Value.ToString();
|
||||
}
|
||||
else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Nvarchar)
|
||||
{
|
||||
dto.VarChar = property.Value.ToString();
|
||||
}
|
||||
|
||||
propertyDataDtos.Add(dto);
|
||||
}
|
||||
return propertyDataDtos;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
@@ -10,166 +11,31 @@ using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a repository for doing CRUD operations for <see cref="Content"/>
|
||||
/// </summary>
|
||||
internal class ContentRepository : Repository<IContent>, IContentRepository
|
||||
internal class ContentRepository : PetaPocoRepositoryBase<int, IContent>, IContentRepository
|
||||
{
|
||||
private const string NodeObjectType = "C66BA18E-EAF3-4CFF-8A22-41B16D66A972";
|
||||
private readonly IContentTypeRepository _contentTypeRepository;
|
||||
|
||||
public ContentRepository(IUnitOfWork<Database> work, IContentTypeRepository contentTypeRepository)
|
||||
public ContentRepository(IUnitOfWork work, IContentTypeRepository contentTypeRepository)
|
||||
: base(work)
|
||||
{
|
||||
_contentTypeRepository = contentTypeRepository;
|
||||
}
|
||||
|
||||
internal ContentRepository(IUnitOfWork<Database> work, IContentTypeRepository contentTypeRepository, IRepositoryCacheProvider registry)
|
||||
: base(work, registry)
|
||||
public ContentRepository(IUnitOfWork work, IRepositoryCacheProvider cache, IContentTypeRepository contentTypeRepository)
|
||||
: base(work, cache)
|
||||
{
|
||||
_contentTypeRepository = contentTypeRepository;
|
||||
}
|
||||
|
||||
protected override void PerformAdd(IContent entity)
|
||||
{
|
||||
((Content)entity).AddingEntity();
|
||||
|
||||
//NOTE Should the logic below have some kind of fallback for empty parent ids ?
|
||||
//Logic for setting Path, Level and SortOrder
|
||||
var parent = UnitOfWork.Storage.First<NodeDto>("WHERE id = @ParentId", new { ParentId = entity.ParentId });
|
||||
int level = parent.Level + 1;
|
||||
int sortOrder =
|
||||
UnitOfWork.Storage.ExecuteScalar<int>("SELECT COUNT(*) FROM umbracoNode WHERE parentID = @ParentId AND nodeObjectType = @NodeObjectType",
|
||||
new { ParentId = entity.ParentId, NodeObjectType = NodeObjectType });
|
||||
|
||||
//Create the (base) node data - umbracoNode
|
||||
var nodeDto = ContentFactory.CreateNodeDto(entity, NodeObjectType, parent.Path, level, sortOrder);
|
||||
var o = UnitOfWork.Storage.IsNew(nodeDto) ? Convert.ToInt32(UnitOfWork.Storage.Insert(nodeDto)) : UnitOfWork.Storage.Update(nodeDto);
|
||||
|
||||
//Update with new correct path
|
||||
nodeDto.Path = string.Concat(parent.Path, ",", nodeDto.NodeId);
|
||||
UnitOfWork.Storage.Update(nodeDto);
|
||||
|
||||
//Update entity with correct values
|
||||
entity.Id = nodeDto.NodeId; //Set Id on entity to ensure an Id is set
|
||||
entity.Path = nodeDto.Path;
|
||||
entity.SortOrder = sortOrder;
|
||||
entity.Level = level;
|
||||
|
||||
//Create the Content specific data - cmsContent
|
||||
var contentDto = ContentFactory.CreateContentDto(entity);
|
||||
UnitOfWork.Storage.Insert(contentDto);
|
||||
|
||||
//Create the first version - cmsContentVersion
|
||||
//Assumes a new Version guid and Version date (modified date) has been set
|
||||
var contentVersionDto = ContentFactory.CreateContentVersionDto(entity);
|
||||
UnitOfWork.Storage.Insert(contentVersionDto);
|
||||
|
||||
//Create the Document specific data for this version - cmsDocument
|
||||
//Assumes a new Version guid has been generated
|
||||
var documentDto = ContentFactory.CreateDocumentDto(entity);
|
||||
UnitOfWork.Storage.Insert(documentDto);
|
||||
|
||||
//Create the PropertyData for this version - cmsPropertyData
|
||||
var propertyDataDtos = ContentFactory.CreateProperties(entity.Id, entity.Version, entity.Properties);
|
||||
//Add Properties
|
||||
foreach (var propertyDataDto in propertyDataDtos)
|
||||
{
|
||||
UnitOfWork.Storage.Insert(propertyDataDto);
|
||||
}
|
||||
|
||||
((Content)entity).ResetDirtyProperties();
|
||||
}
|
||||
|
||||
protected override void PerformUpdate(IContent entity)
|
||||
{
|
||||
//Updates Modified date and Version Guid
|
||||
((Content)entity).UpdatingEntity();
|
||||
|
||||
//Updates the (base) node data - umbracoNode
|
||||
var nodeDto = ContentFactory.CreateNodeDto(entity, NodeObjectType);
|
||||
var o = UnitOfWork.Storage.Update(nodeDto);
|
||||
|
||||
//Look up Content entry to get Primary for updating the DTO
|
||||
var contentDto = UnitOfWork.Storage.SingleOrDefault<ContentDto>("WHERE nodeId = @Id", new { Id = entity.Id });
|
||||
//Only update this DTO if the contentType has actually changed
|
||||
if (contentDto.ContentType != entity.ContentTypeId)
|
||||
{
|
||||
//Create the Content specific data - cmsContent
|
||||
var newContentDto = ContentFactory.CreateContentDto(entity, contentDto.PrimaryKey);
|
||||
UnitOfWork.Storage.Update(newContentDto);
|
||||
}
|
||||
|
||||
//Look up entries in cmsDocument table to set newest = false
|
||||
var documentDtos = UnitOfWork.Storage.Fetch<DocumentDto>("WHERE nodeId = @Id AND newest = '1'", new { Id = entity.Id });
|
||||
foreach (var docDto in documentDtos)
|
||||
{
|
||||
var dto = docDto;
|
||||
dto.Newest = false;
|
||||
UnitOfWork.Storage.Update(dto);
|
||||
}
|
||||
|
||||
//Create a new version - cmsContentVersion
|
||||
//Assumes a new Version guid and Version date (modified date) has been set
|
||||
var contentVersionDto = ContentFactory.CreateContentVersionDto(entity);
|
||||
UnitOfWork.Storage.Insert(contentVersionDto);
|
||||
|
||||
//Create the Document specific data for this version - cmsDocument
|
||||
//Assumes a new Version guid has been generated
|
||||
var documentDto = ContentFactory.CreateDocumentDto(entity);
|
||||
UnitOfWork.Storage.Insert(documentDto);
|
||||
|
||||
//Create the PropertyData for this version - cmsPropertyData
|
||||
var propertyDataDtos = ContentFactory.CreateProperties(entity.Id, entity.Version, entity.Properties);
|
||||
//Add Properties
|
||||
foreach (var propertyDataDto in propertyDataDtos)
|
||||
{
|
||||
UnitOfWork.Storage.Insert(propertyDataDto);
|
||||
}
|
||||
|
||||
((Content)entity).ResetDirtyProperties();
|
||||
}
|
||||
|
||||
protected override void PerformDelete(IContent entity)
|
||||
{
|
||||
//Remove Notifications
|
||||
UnitOfWork.Storage.Delete<User2NodeNotifyDto>("WHERE nodeId = @Id", new { Id = entity.Id });
|
||||
|
||||
//Remove Permissions
|
||||
UnitOfWork.Storage.Delete<User2NodePermissionDto>("WHERE nodeId = @Id", new { Id = entity.Id });
|
||||
|
||||
//Remove associated tags
|
||||
UnitOfWork.Storage.Delete<TagRelationshipDto>("WHERE nodeId = @Id", new { Id = entity.Id });
|
||||
|
||||
//Delete entry in Document table
|
||||
UnitOfWork.Storage.Delete<DocumentDto>("WHERE NodeId = @Id", new { Id = entity.Id });
|
||||
|
||||
//Delete Properties
|
||||
UnitOfWork.Storage.Delete<PropertyDataDto>("WHERE contentNodeId = @Id", new { Id = entity.Id });
|
||||
|
||||
//Delete Preview Xml
|
||||
UnitOfWork.Storage.Delete<PreviewXmlDto>("WHERE nodeId = @Id", new { Id = entity.Id });
|
||||
|
||||
//Delete Version history
|
||||
UnitOfWork.Storage.Delete<ContentVersionDto>("WHERE ContentId = @Id", new { Id = entity.Id });
|
||||
|
||||
//Delete Content Xml
|
||||
UnitOfWork.Storage.Delete<ContentXmlDto>("WHERE nodeID = @Id", new { Id = entity.Id });
|
||||
|
||||
//Delete Content specific data
|
||||
UnitOfWork.Storage.Delete<ContentDto>("WHERE NodeId = @Id", new { Id = entity.Id });
|
||||
|
||||
//Delete (base) node data
|
||||
UnitOfWork.Storage.Delete<NodeDto>("WHERE uniqueID = @Id", new { Id = entity.Key });
|
||||
}
|
||||
#region Overrides of RepositoryBase<IContent>
|
||||
|
||||
protected override IContent PerformGet(int id)
|
||||
{
|
||||
var contentSql = BaseSqlClause(false);
|
||||
var contentSql = GetBaseQuery(false);
|
||||
contentSql.Where("[cmsDocument].[nodeId] = @Id", new { Id = id });
|
||||
contentSql.OrderBy("[cmsContentVersion].[VersionDate] DESC");
|
||||
|
||||
var documentDto = UnitOfWork.Storage.Query<DocumentDto, ContentVersionDto, ContentDto, NodeDto>(contentSql).FirstOrDefault();
|
||||
var documentDto = Database.Query<DocumentDto, ContentVersionDto, ContentDto, NodeDto>(contentSql).FirstOrDefault();
|
||||
|
||||
if (documentDto == null)
|
||||
return null;
|
||||
@@ -181,11 +47,19 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
propertySql.Where("[cmsPropertyData].[contentNodeId] = @Id", new { Id = id });
|
||||
propertySql.Where("[cmsPropertyData].[versionId] = @VersionId", new { VersionId = documentDto.ContentVersionDto.VersionId });
|
||||
|
||||
var propertyDataDtos = UnitOfWork.Storage.Fetch<PropertyDataDto, PropertyTypeDto>(propertySql);
|
||||
var propertyDataDtos = Database.Fetch<PropertyDataDto, PropertyTypeDto>(propertySql);
|
||||
|
||||
var contentType = _contentTypeRepository.Get(documentDto.ContentVersionDto.ContentDto.ContentType);
|
||||
var content = ContentFactory.CreateContent(id, contentType, documentDto, propertyDataDtos);
|
||||
content.ResetDirtyProperties();
|
||||
//var content = ContentFactory.CreateContent(id, contentType, documentDto, propertyDataDtos);
|
||||
|
||||
var factory = new EntityFactory(contentType, NodeObjectTypeId, id);
|
||||
var content = factory.BuildEntity(documentDto);
|
||||
|
||||
var propertyFactory = new PropertyFactory(contentType, documentDto.ContentVersionDto.VersionId, id);
|
||||
var properties = propertyFactory.BuildEntity(propertyDataDtos);
|
||||
content.Properties = new PropertyCollection(properties);
|
||||
|
||||
((Content)content).ResetDirtyProperties();
|
||||
return content;
|
||||
}
|
||||
|
||||
@@ -200,7 +74,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
else
|
||||
{
|
||||
var nodeDtos = UnitOfWork.Storage.Fetch<NodeDto>("WHERE nodeObjectType = @NodeObjectType", new { NodeObjectType = NodeObjectType });
|
||||
var nodeDtos = Database.Fetch<NodeDto>("WHERE nodeObjectType = @NodeObjectType", new { NodeObjectType = NodeObjectTypeId });
|
||||
foreach (var nodeDto in nodeDtos)
|
||||
{
|
||||
yield return Get(nodeDto.NodeId);
|
||||
@@ -210,11 +84,11 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
protected override IEnumerable<IContent> PerformGetByQuery(IQuery<IContent> query)
|
||||
{
|
||||
var sqlClause = BaseSqlClause(false);
|
||||
var sqlClause = GetBaseQuery(false);
|
||||
var translator = new SqlTranslator<IContent>(sqlClause, query);
|
||||
var sql = translator.Translate();
|
||||
|
||||
var documentDtos = UnitOfWork.Storage.Fetch<DocumentDto, ContentVersionDto, ContentDto, NodeDto>(sql);
|
||||
var documentDtos = Database.Fetch<DocumentDto, ContentVersionDto, ContentDto, NodeDto>(sql);
|
||||
|
||||
foreach (var documentDto in documentDtos)
|
||||
{
|
||||
@@ -224,25 +98,189 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
protected override bool PerformExists(int id)
|
||||
{
|
||||
return UnitOfWork.Storage.Exists<NodeDto>(id);
|
||||
return Database.Exists<NodeDto>(id);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected override int PerformCount(IQuery<IContent> query)
|
||||
#region Overrides of PetaPocoRepositoryBase<IContent>
|
||||
|
||||
protected override Sql GetBaseQuery(bool isCount)
|
||||
{
|
||||
var sqlClause = BaseSqlClause(true);
|
||||
var translator = new SqlTranslator<IContent>(sqlClause, query);
|
||||
var sql = translator.Translate();
|
||||
|
||||
return UnitOfWork.Storage.ExecuteScalar<int>(sql);
|
||||
var sql = new Sql();
|
||||
sql.Select(isCount ? "COUNT(*)" : "*");
|
||||
sql.From("cmsDocument");
|
||||
sql.InnerJoin("cmsContentVersion ON ([cmsDocument].[versionId] = [cmsContentVersion].[VersionId])");
|
||||
sql.InnerJoin("cmsContent ON ([cmsContentVersion].[ContentId] = [cmsContent].[nodeId])");
|
||||
sql.InnerJoin("umbracoNode ON ([cmsContent].[nodeId] = [umbracoNode].[id])");
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected override Sql GetBaseWhereClause()
|
||||
{
|
||||
var sql = new Sql();
|
||||
sql.Where("[umbracoNode].[nodeObjectType] = @NodeObjectType", new { NodeObjectType = NodeObjectTypeId });
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected override IEnumerable<string> GetDeleteClauses()
|
||||
{
|
||||
var list = new List<string>
|
||||
{
|
||||
string.Format("DELETE FROM umbracoUser2NodeNotify WHERE nodeId = @Id"),
|
||||
string.Format("DELETE FROM umbracoUser2NodePermission WHERE nodeId = @Id"),
|
||||
string.Format("DELETE FROM cmsTagRelationship WHERE nodeId = @Id"),
|
||||
string.Format("DELETE FROM cmsDocument WHERE NodeId = @Id"),
|
||||
string.Format("DELETE FROM cmsPropertyData WHERE contentNodeId = @Id"),
|
||||
string.Format("DELETE FROM cmsPreviewXml WHERE nodeId = @Id"),
|
||||
string.Format("DELETE FROM cmsContentVersion WHERE ContentId = @Id"),
|
||||
string.Format("DELETE FROM cmsContentXml WHERE nodeID = @Id"),
|
||||
string.Format("DELETE FROM cmsContent WHERE NodeId = @Id"),
|
||||
string.Format("DELETE FROM umbracoNode WHERE id = @Id")
|
||||
};
|
||||
return list;
|
||||
}
|
||||
|
||||
protected override Guid NodeObjectTypeId
|
||||
{
|
||||
get { return new Guid("C66BA18E-EAF3-4CFF-8A22-41B16D66A972"); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unit of Work Implementation
|
||||
|
||||
protected override void PersistNewItem(IContent entity)
|
||||
{
|
||||
((Content)entity).AddingEntity();
|
||||
|
||||
var factory = new EntityFactory(null, NodeObjectTypeId, entity.Id);
|
||||
var dto = factory.BuildDto(entity);
|
||||
|
||||
//NOTE Should the logic below have some kind of fallback for empty parent ids ?
|
||||
//Logic for setting Path, Level and SortOrder
|
||||
var parent = Database.First<NodeDto>("WHERE id = @ParentId", new { ParentId = entity.ParentId });
|
||||
int level = parent.Level + 1;
|
||||
int sortOrder =
|
||||
Database.ExecuteScalar<int>("SELECT COUNT(*) FROM umbracoNode WHERE parentID = @ParentId AND nodeObjectType = @NodeObjectType",
|
||||
new { ParentId = entity.ParentId, NodeObjectType = NodeObjectTypeId });
|
||||
|
||||
//Create the (base) node data - umbracoNode
|
||||
//var nodeDto = ContentFactory.CreateNodeDto(entity, NodeObjectTypeId, parent.Path, level, sortOrder);
|
||||
var nodeDto = dto.ContentVersionDto.ContentDto.NodeDto;
|
||||
nodeDto.Path = parent.Path;
|
||||
nodeDto.Level = short.Parse(level.ToString(CultureInfo.InvariantCulture));
|
||||
nodeDto.SortOrder = sortOrder;
|
||||
var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto);
|
||||
|
||||
//Update with new correct path
|
||||
nodeDto.Path = string.Concat(parent.Path, ",", nodeDto.NodeId);
|
||||
Database.Update(nodeDto);
|
||||
|
||||
//Update entity with correct values
|
||||
entity.Id = nodeDto.NodeId; //Set Id on entity to ensure an Id is set
|
||||
entity.Path = nodeDto.Path;
|
||||
entity.SortOrder = sortOrder;
|
||||
entity.Level = level;
|
||||
|
||||
//Create the Content specific data - cmsContent
|
||||
//var contentDto = ContentFactory.CreateContentDto(entity);
|
||||
var contentDto = dto.ContentVersionDto.ContentDto;
|
||||
Database.Insert(contentDto);
|
||||
|
||||
//Create the first version - cmsContentVersion
|
||||
//Assumes a new Version guid and Version date (modified date) has been set
|
||||
//var contentVersionDto = ContentFactory.CreateContentVersionDto(entity);
|
||||
var contentVersionDto = dto.ContentVersionDto;
|
||||
Database.Insert(contentVersionDto);
|
||||
|
||||
//Create the Document specific data for this version - cmsDocument
|
||||
//Assumes a new Version guid has been generated
|
||||
//var documentDto = ContentFactory.CreateDocumentDto(entity);
|
||||
Database.Insert(dto);
|
||||
|
||||
//Create the PropertyData for this version - cmsPropertyData
|
||||
var propertyFactory = new PropertyFactory(null, entity.Version, entity.Id);
|
||||
var propertyDataDtos = propertyFactory.BuildDto(entity.Properties);
|
||||
//var propertyDataDtos = ContentFactory.CreateProperties(entity.Id, entity.Version, entity.Properties);
|
||||
//Add Properties
|
||||
foreach (var propertyDataDto in propertyDataDtos)
|
||||
{
|
||||
Database.Insert(propertyDataDto);
|
||||
}
|
||||
|
||||
((Content)entity).ResetDirtyProperties();
|
||||
}
|
||||
|
||||
protected override void PersistUpdatedItem(IContent entity)
|
||||
{
|
||||
//Updates Modified date and Version Guid
|
||||
((Content)entity).UpdatingEntity();
|
||||
|
||||
var factory = new EntityFactory(null, NodeObjectTypeId, entity.Id);
|
||||
//Look up Content entry to get Primary for updating the DTO
|
||||
var contentDto = Database.SingleOrDefault<ContentDto>("WHERE nodeId = @Id", new { Id = entity.Id });
|
||||
factory.SetPrimaryKey(contentDto.PrimaryKey);
|
||||
var dto = factory.BuildDto(entity);
|
||||
|
||||
//Updates the (base) node data - umbracoNode
|
||||
//var nodeDto = ContentFactory.CreateNodeDto(entity, NodeObjectTypeId);
|
||||
var nodeDto = dto.ContentVersionDto.ContentDto.NodeDto;
|
||||
var o = Database.Update(nodeDto);
|
||||
|
||||
//Only update this DTO if the contentType has actually changed
|
||||
if (contentDto.ContentType != entity.ContentTypeId)
|
||||
{
|
||||
//Create the Content specific data - cmsContent
|
||||
//var newContentDto = ContentFactory.CreateContentDto(entity, contentDto.PrimaryKey);
|
||||
var newContentDto = dto.ContentVersionDto.ContentDto;
|
||||
Database.Update(newContentDto);
|
||||
}
|
||||
|
||||
//Look up entries in cmsDocument table to set newest = false
|
||||
var documentDtos = Database.Fetch<DocumentDto>("WHERE nodeId = @Id AND newest = '1'", new { Id = entity.Id });
|
||||
foreach (var documentDto in documentDtos)
|
||||
{
|
||||
var docDto = documentDto;
|
||||
docDto.Newest = false;
|
||||
Database.Update(docDto);
|
||||
}
|
||||
|
||||
//Create a new version - cmsContentVersion
|
||||
//Assumes a new Version guid and Version date (modified date) has been set
|
||||
//var contentVersionDto = ContentFactory.CreateContentVersionDto(entity);
|
||||
var contentVersionDto = dto.ContentVersionDto;
|
||||
Database.Insert(contentVersionDto);
|
||||
|
||||
//Create the Document specific data for this version - cmsDocument
|
||||
//Assumes a new Version guid has been generated
|
||||
//var documentDto = ContentFactory.CreateDocumentDto(entity);
|
||||
Database.Insert(dto);
|
||||
|
||||
//Create the PropertyData for this version - cmsPropertyData
|
||||
//var propertyDataDtos = ContentFactory.CreateProperties(entity.Id, entity.Version, entity.Properties);
|
||||
var propertyFactory = new PropertyFactory(null, entity.Version, entity.Id);
|
||||
var propertyDataDtos = propertyFactory.BuildDto(entity.Properties);
|
||||
//Add Properties
|
||||
foreach (var propertyDataDto in propertyDataDtos)
|
||||
{
|
||||
Database.Insert(propertyDataDto);
|
||||
}
|
||||
|
||||
((Content)entity).ResetDirtyProperties();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of IContentRepository
|
||||
|
||||
public IEnumerable<IContent> GetAllVersions(int id)
|
||||
{
|
||||
var contentSql = BaseSqlClause(false);
|
||||
var contentSql = GetBaseQuery(false);
|
||||
contentSql.Where("[cmsDocument].[nodeId] = @Id", new { Id = id });
|
||||
contentSql.OrderBy("[cmsContentVersion].[VersionDate] DESC");
|
||||
|
||||
var documentDtos = UnitOfWork.Storage.Fetch<DocumentDto, ContentVersionDto, ContentDto, NodeDto>(contentSql);
|
||||
var documentDtos = Database.Fetch<DocumentDto, ContentVersionDto, ContentDto, NodeDto>(contentSql);
|
||||
foreach (var dto in documentDtos)
|
||||
{
|
||||
yield return GetByVersion(id, dto.ContentVersionDto.VersionId);
|
||||
@@ -251,12 +289,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public IContent GetByVersion(int id, Guid versionId)
|
||||
{
|
||||
var contentSql = BaseSqlClause(false);
|
||||
var contentSql = GetBaseQuery(false);
|
||||
contentSql.Where("[cmsDocument].[nodeId] = @Id", new { Id = id });
|
||||
contentSql.Where("[cmsContentVersion].[VersionId] = @VersionId", new { VersionId = versionId });
|
||||
contentSql.OrderBy("[cmsContentVersion].[VersionDate] DESC");
|
||||
|
||||
var documentDto = UnitOfWork.Storage.Query<DocumentDto, ContentVersionDto, ContentDto, NodeDto>(contentSql).FirstOrDefault();
|
||||
var documentDto = Database.Query<DocumentDto, ContentVersionDto, ContentDto, NodeDto>(contentSql).FirstOrDefault();
|
||||
|
||||
if (documentDto == null)
|
||||
return null;
|
||||
@@ -268,26 +306,22 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
propertySql.Where("[cmsPropertyData].[contentNodeId] = @Id", new { Id = id });
|
||||
propertySql.Where("[cmsPropertyData].[versionId] = @VersionId", new { VersionId = versionId });
|
||||
|
||||
var propertyDataDtos = UnitOfWork.Storage.Query<PropertyDataDto, PropertyTypeDto>(propertySql);
|
||||
var propertyDataDtos = Database.Query<PropertyDataDto, PropertyTypeDto>(propertySql);
|
||||
|
||||
var contentType = _contentTypeRepository.Get(documentDto.ContentVersionDto.ContentDto.ContentType);
|
||||
var content = ContentFactory.CreateContent(id, contentType, documentDto, propertyDataDtos);
|
||||
content.ResetDirtyProperties();
|
||||
//var content = ContentFactory.CreateContent(id, contentType, documentDto, propertyDataDtos);
|
||||
|
||||
var factory = new EntityFactory(contentType, NodeObjectTypeId, id);
|
||||
var content = factory.BuildEntity(documentDto);
|
||||
|
||||
var propertyFactory = new PropertyFactory(contentType, documentDto.ContentVersionDto.VersionId, id);
|
||||
var properties = propertyFactory.BuildEntity(propertyDataDtos);
|
||||
content.Properties = new PropertyCollection(properties);
|
||||
|
||||
((Content)content).ResetDirtyProperties();
|
||||
return content;
|
||||
}
|
||||
|
||||
private Sql BaseSqlClause(bool doCount)
|
||||
{
|
||||
var sql = new Sql();
|
||||
|
||||
sql.Select(doCount ? "COUNT(*)" : "*");
|
||||
sql.From("cmsDocument");
|
||||
sql.InnerJoin("cmsContentVersion ON ([cmsDocument].[versionId]=[cmsContentVersion].[VersionId])");
|
||||
sql.InnerJoin("cmsContent ON ([cmsContentVersion].[ContentId]=[cmsContent].[nodeId])");
|
||||
sql.InnerJoin("umbracoNode ON ([cmsContent].[nodeId]=[umbracoNode].[id])");
|
||||
sql.Where("[umbracoNode].[nodeObjectType]=@NodeObjectType", new { NodeObjectType = NodeObjectType });
|
||||
|
||||
return sql;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public interface IContentRepository : IRepository<IContent>
|
||||
public interface IContentRepository : IRepository<int, IContent>
|
||||
{
|
||||
IEnumerable<IContent> GetAllVersions(int id);
|
||||
IContent GetByVersion(int id, Guid versionId);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public interface IContentTypeRepository : IRepository<IContentType>
|
||||
public interface IContentTypeRepository : IRepository<int, IContentType>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -9,7 +9,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// Defines the implementation of a Repository
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity">Type of <see cref="IAggregateRoot"/> entity for which the repository is used</typeparam>
|
||||
public interface IRepository<TEntity> where TEntity : class, IAggregateRoot
|
||||
/// <typeparam name="TId">Type of the Id used for this entity</typeparam>
|
||||
public interface IRepository<TId, TEntity>
|
||||
where TEntity : IAggregateRoot
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds or Updates an Entity
|
||||
@@ -28,14 +30,14 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
TEntity Get(int id);
|
||||
TEntity Get(TId id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all entities of the spefified type
|
||||
/// </summary>
|
||||
/// <param name="ids"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<TEntity> GetAll(params int[] ids);
|
||||
IEnumerable<TEntity> GetAll(params TId[] ids);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all entities of the spefified type and query
|
||||
@@ -49,7 +51,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
bool Exists(int id);
|
||||
bool Exists(TId id);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the count for the specified query
|
||||
@@ -62,6 +64,6 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// Sets the Unit Of Work for the Repository
|
||||
/// </summary>
|
||||
/// <param name="work"></param>
|
||||
void SetUnitOfWork<T>(IUnitOfWork<T> work);
|
||||
void SetUnitOfWork(IUnitOfWork work);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Caching;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
/// <summary>
|
||||
/// Represent an abstract Repository for PetaPoco based repositories
|
||||
/// </summary>
|
||||
/// <typeparam name="TId"></typeparam>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
internal abstract class PetaPocoRepositoryBase<TId, TEntity> : RepositoryBase<TId, TEntity>
|
||||
where TEntity : IAggregateRoot
|
||||
{
|
||||
private Database _database;
|
||||
|
||||
protected PetaPocoRepositoryBase(IUnitOfWork work) : base(work)
|
||||
{
|
||||
}
|
||||
|
||||
protected PetaPocoRepositoryBase(IUnitOfWork work, IRepositoryCacheProvider cache) : base(work, cache)
|
||||
{
|
||||
_database = DatabaseFactory.Current.Database;
|
||||
}
|
||||
|
||||
protected Database Database
|
||||
{
|
||||
get { return _database; }
|
||||
}
|
||||
|
||||
#region Abstract Methods
|
||||
|
||||
protected abstract Sql GetBaseQuery(bool isCount);
|
||||
protected abstract Sql GetBaseWhereClause();
|
||||
protected abstract IEnumerable<string> GetDeleteClauses();
|
||||
protected abstract Guid NodeObjectTypeId { get; }
|
||||
protected abstract override void PersistNewItem(TEntity entity);
|
||||
protected abstract override void PersistUpdatedItem(TEntity entity);
|
||||
|
||||
#endregion
|
||||
|
||||
protected override int PerformCount(IQuery<TEntity> query)
|
||||
{
|
||||
var sqlClause = GetBaseQuery(true);
|
||||
var translator = new SqlTranslator<TEntity>(sqlClause, query);
|
||||
var sql = translator.Translate();
|
||||
|
||||
return _database.ExecuteScalar<int>(sql);
|
||||
}
|
||||
|
||||
protected override void PersistDeletedItem(TEntity entity)
|
||||
{
|
||||
var deletes = GetDeleteClauses();
|
||||
foreach (var delete in deletes)
|
||||
{
|
||||
_database.Execute(delete, new {Id = entity.Id});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Caching;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
/// <summary>
|
||||
/// Represent an abstract Repository, which is the base of the Repository implementations
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
internal abstract class Repository<TEntity> : IDisposable,
|
||||
IRepository<TEntity> where TEntity : class, IAggregateRoot
|
||||
{
|
||||
private IUnitOfWork<Database> _work;
|
||||
private readonly IRepositoryCacheProvider _cache;
|
||||
|
||||
protected Repository(IUnitOfWork<Database> work)
|
||||
: this(work, RuntimeCacheProvider.Current)
|
||||
{
|
||||
}
|
||||
|
||||
internal Repository(IUnitOfWork<Database> work, IRepositoryCacheProvider cache)
|
||||
{
|
||||
_work = work;
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
internal IUnitOfWork<Database> UnitOfWork
|
||||
{
|
||||
get { return _work; }
|
||||
}
|
||||
|
||||
protected abstract void PerformAdd(TEntity entity);
|
||||
protected abstract void PerformUpdate(TEntity entity);
|
||||
public void AddOrUpdate(TEntity entity)
|
||||
{
|
||||
if (!entity.HasIdentity)
|
||||
{
|
||||
PerformAdd(entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
PerformUpdate(entity);
|
||||
}
|
||||
|
||||
_cache.Save(typeof(TEntity), entity);
|
||||
}
|
||||
|
||||
protected abstract void PerformDelete(TEntity entity);
|
||||
public void Delete(TEntity entity)
|
||||
{
|
||||
_cache.Delete(typeof(TEntity), entity);
|
||||
PerformDelete(entity);
|
||||
}
|
||||
|
||||
protected abstract TEntity PerformGet(int id);
|
||||
public TEntity Get(int id)
|
||||
{
|
||||
var rEntity = _cache.GetById(typeof(TEntity), ConvertIdToGuid(id));
|
||||
if (rEntity != null)
|
||||
{
|
||||
return (TEntity)rEntity;
|
||||
}
|
||||
|
||||
var entity = PerformGet(id);
|
||||
if (entity != null)
|
||||
{
|
||||
_cache.Save(typeof(TEntity), entity);
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
protected abstract IEnumerable<TEntity> PerformGetAll(params int[] ids);
|
||||
public IEnumerable<TEntity> GetAll(params int[] ids)
|
||||
{
|
||||
if (ids.Any())
|
||||
{
|
||||
var entities = _cache.GetByIds(typeof(TEntity), ids.Select(ConvertIdToGuid).ToList());
|
||||
if (ids.Count().Equals(entities.Count()))
|
||||
return entities.Select(x => (TEntity)x);
|
||||
}
|
||||
else
|
||||
{
|
||||
var allEntities = _cache.GetAllByType(typeof(TEntity));
|
||||
if (allEntities.Any())
|
||||
return allEntities.Select(x => (TEntity)x);
|
||||
}
|
||||
|
||||
var entityCollection = PerformGetAll(ids);
|
||||
|
||||
foreach (var entity in entityCollection)
|
||||
{
|
||||
if (entity != null)
|
||||
{
|
||||
_cache.Save(typeof(TEntity), entity);
|
||||
}
|
||||
}
|
||||
|
||||
return entityCollection;
|
||||
}
|
||||
|
||||
protected abstract IEnumerable<TEntity> PerformGetByQuery(IQuery<TEntity> query);
|
||||
public IEnumerable<TEntity> GetByQuery(IQuery<TEntity> query)
|
||||
{
|
||||
return PerformGetByQuery(query);
|
||||
}
|
||||
|
||||
protected abstract bool PerformExists(int id);
|
||||
public bool Exists(int id)
|
||||
{
|
||||
var rEntity = _cache.GetById(typeof(TEntity), ConvertIdToGuid(id));
|
||||
if (rEntity != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return PerformExists(id);
|
||||
}
|
||||
|
||||
protected abstract int PerformCount(IQuery<TEntity> query);
|
||||
public int Count(IQuery<TEntity> query)
|
||||
{
|
||||
return PerformCount(query);
|
||||
}
|
||||
|
||||
public void SetUnitOfWork<T>(IUnitOfWork<T> work)
|
||||
{
|
||||
_work = work as IUnitOfWork<Database>;
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
_work.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal method that handles the convertion of an object Id
|
||||
/// to an Integer and then a Guid Id.
|
||||
/// </summary>
|
||||
/// <remarks>In the future it should be possible to change this method
|
||||
/// so it converts from object to guid if/when we decide to go from
|
||||
/// int to guid based ids.</remarks>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual Guid ConvertIdToGuid(int id)
|
||||
{
|
||||
return id.ToGuid();
|
||||
}
|
||||
}
|
||||
}
|
||||
247
src/Umbraco.Core/Persistence/Repositories/RepositoryBase.cs
Normal file
247
src/Umbraco.Core/Persistence/Repositories/RepositoryBase.cs
Normal file
@@ -0,0 +1,247 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Caching;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
/// <summary>
|
||||
/// Represent an abstract Repository, which is the base of the Repository implementations
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity">Type of <see cref="IAggregateRoot"/> entity for which the repository is used</typeparam>
|
||||
/// <typeparam name="TId">Type of the Id used for this entity</typeparam>
|
||||
internal abstract class RepositoryBase<TId, TEntity> : IRepository<TId, TEntity>,
|
||||
IUnitOfWorkRepository where TEntity : IAggregateRoot
|
||||
{
|
||||
private IUnitOfWork _work;
|
||||
private readonly IRepositoryCacheProvider _cache;
|
||||
|
||||
protected RepositoryBase(IUnitOfWork work)
|
||||
: this(work, RuntimeCacheProvider.Current)
|
||||
{
|
||||
}
|
||||
|
||||
internal RepositoryBase(IUnitOfWork work, IRepositoryCacheProvider cache)
|
||||
{
|
||||
_work = work;
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Unit of Work added to the repository
|
||||
/// </summary>
|
||||
protected IUnitOfWork UnitOfWork
|
||||
{
|
||||
get { return _work; }
|
||||
}
|
||||
|
||||
#region IRepository<TEntity> Members
|
||||
|
||||
/// <summary>
|
||||
/// Adds or Updates an entity of type TEntity
|
||||
/// </summary>
|
||||
/// <remarks>This method is backed by an <see cref="IRepositoryCacheProvider"/> cache</remarks>
|
||||
/// <param name="entity"></param>
|
||||
public void AddOrUpdate(TEntity entity)
|
||||
{
|
||||
if (!entity.HasIdentity)
|
||||
{
|
||||
_work.RegisterAdded(entity, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
_work.RegisterChanged(entity, this);
|
||||
}
|
||||
|
||||
_cache.Save(typeof(TEntity), entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the passed in entity
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
public void Delete(TEntity entity)
|
||||
{
|
||||
_cache.Delete(typeof(TEntity), entity);
|
||||
if(_work != null)
|
||||
{
|
||||
_work.RegisterRemoved(entity, this);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract TEntity PerformGet(TId id);
|
||||
/// <summary>
|
||||
/// Gets an entity by the passed in Id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public TEntity Get(TId id)
|
||||
{
|
||||
Guid key = id is int ? ConvertIdToGuid(id) : ConvertStringIdToGuid(id.ToString());
|
||||
var rEntity = _cache.GetById(typeof(TEntity), key);
|
||||
if (rEntity != null)
|
||||
{
|
||||
return (TEntity)rEntity;
|
||||
}
|
||||
|
||||
var entity = PerformGet(id);
|
||||
if (entity != null)
|
||||
{
|
||||
_cache.Save(typeof(TEntity), entity);
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
protected abstract IEnumerable<TEntity> PerformGetAll(params TId[] ids);
|
||||
/// <summary>
|
||||
/// Gets all entities of type TEntity or a list according to the passed in Ids
|
||||
/// </summary>
|
||||
/// <param name="ids"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<TEntity> GetAll(params TId[] ids)
|
||||
{
|
||||
if (ids.Any())
|
||||
{
|
||||
var entities = _cache.GetByIds(typeof(TEntity), ids.Select(id => id is int ? ConvertIdToGuid(id) : ConvertStringIdToGuid(id.ToString())).ToList());
|
||||
if (ids.Count().Equals(entities.Count()))
|
||||
return entities.Select(x => (TEntity)x);
|
||||
}
|
||||
else
|
||||
{
|
||||
var allEntities = _cache.GetAllByType(typeof(TEntity));
|
||||
if (allEntities.Any())
|
||||
return allEntities.Select(x => (TEntity)x);
|
||||
}
|
||||
|
||||
var entityCollection = PerformGetAll(ids);
|
||||
|
||||
foreach (var entity in entityCollection)
|
||||
{
|
||||
if (entity != null)
|
||||
{
|
||||
_cache.Save(typeof(TEntity), entity);
|
||||
}
|
||||
}
|
||||
|
||||
return entityCollection;
|
||||
}
|
||||
|
||||
protected abstract IEnumerable<TEntity> PerformGetByQuery(IQuery<TEntity> query);
|
||||
/// <summary>
|
||||
/// Gets a list of entities by the passed in query
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<TEntity> GetByQuery(IQuery<TEntity> query)
|
||||
{
|
||||
return PerformGetByQuery(query);
|
||||
}
|
||||
|
||||
protected abstract bool PerformExists(TId id);
|
||||
/// <summary>
|
||||
/// Returns a boolean indicating whether an entity with the passed Id exists
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public bool Exists(TId id)
|
||||
{
|
||||
Guid key = id is int ? ConvertIdToGuid(id) : ConvertStringIdToGuid(id.ToString());
|
||||
var rEntity = _cache.GetById(typeof(TEntity), key);
|
||||
if (rEntity != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return PerformExists(id);
|
||||
}
|
||||
|
||||
protected abstract int PerformCount(IQuery<TEntity> query);
|
||||
/// <summary>
|
||||
/// Returns an integer with the count of entities found with the passed in query
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <returns></returns>
|
||||
public int Count(IQuery<TEntity> query)
|
||||
{
|
||||
return PerformCount(query);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the repository's Unit Of Work with the passed in <see cref="IUnitOfWork"/>
|
||||
/// </summary>
|
||||
/// <param name="work"></param>
|
||||
public void SetUnitOfWork(IUnitOfWork work)
|
||||
{
|
||||
_work = work;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IUnitOfWorkRepository Members
|
||||
|
||||
/// <summary>
|
||||
/// Unit of work method that tells the repository to persist the new entity
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
public virtual void PersistNewItem(IEntity item)
|
||||
{
|
||||
PersistNewItem((TEntity)item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unit of work method that tells the repository to persist the updated entity
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
public virtual void PersistUpdatedItem(IEntity item)
|
||||
{
|
||||
PersistUpdatedItem((TEntity)item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unit of work method that tells the repository to persist the deletion of the entity
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
public virtual void PersistDeletedItem(IEntity item)
|
||||
{
|
||||
PersistDeletedItem((TEntity)item);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Abstract IUnitOfWorkRepository Methods
|
||||
|
||||
protected abstract void PersistNewItem(TEntity item);
|
||||
protected abstract void PersistUpdatedItem(TEntity item);
|
||||
protected abstract void PersistDeletedItem(TEntity item);
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Internal method that handles the convertion of an object Id
|
||||
/// to an Integer and then a Guid Id.
|
||||
/// </summary>
|
||||
/// <remarks>In the future it should be possible to change this method
|
||||
/// so it converts from object to guid if/when we decide to go from
|
||||
/// int to guid based ids.</remarks>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual Guid ConvertIdToGuid(TId id)
|
||||
{
|
||||
int i = 0;
|
||||
if(int.TryParse(id.ToString(), out i))
|
||||
{
|
||||
return i.ToGuid();
|
||||
}
|
||||
return ConvertStringIdToGuid(id.ToString());
|
||||
}
|
||||
|
||||
protected virtual Guid ConvertStringIdToGuid(string id)
|
||||
{
|
||||
return id.EncodeAsGuid();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,8 @@ namespace Umbraco.Core.Persistence
|
||||
//Otherwise look for an entity type in the config
|
||||
//- If type exists check dependencies, create new object, add it to dictionary and return it
|
||||
//If we have come this far the correct types wasn't found and we throw an exception
|
||||
internal static TRepository ResolveByType<TRepository, TEntity>(IUnitOfWork<Database> unitOfWork)
|
||||
where TRepository : class, IRepository<TEntity>
|
||||
internal static TRepository ResolveByType<TRepository, TEntity, TId>(IUnitOfWork unitOfWork)
|
||||
where TRepository : class, IRepository<TId, TEntity>
|
||||
where TEntity : class, IAggregateRoot
|
||||
{
|
||||
//Initialize the provider's default value
|
||||
@@ -36,7 +36,7 @@ namespace Umbraco.Core.Persistence
|
||||
if (Repositories.ContainsKey(interfaceShortName))
|
||||
{
|
||||
repository = (TRepository)Repositories[interfaceShortName];
|
||||
if (unitOfWork != null && repository.GetType().IsSubclassOf(typeof(IRepository<TEntity>)))
|
||||
if (unitOfWork != null && repository.GetType().IsSubclassOf(typeof(IRepository<TId, TEntity>)))
|
||||
{
|
||||
repository.SetUnitOfWork(unitOfWork);
|
||||
}
|
||||
@@ -83,7 +83,7 @@ namespace Umbraco.Core.Persistence
|
||||
}
|
||||
|
||||
//Recursive create and dependency check
|
||||
private static object Resolve(Type repositoryType, IUnitOfWork<Database> unitOfWork)
|
||||
private static object Resolve(Type repositoryType, IUnitOfWork unitOfWork)
|
||||
{
|
||||
var constructor = repositoryType.GetConstructors().SingleOrDefault();
|
||||
if (constructor == null)
|
||||
|
||||
9
src/Umbraco.Core/Persistence/TransactionType.cs
Normal file
9
src/Umbraco.Core/Persistence/TransactionType.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Umbraco.Core.Persistence
|
||||
{
|
||||
internal enum TransactionType
|
||||
{
|
||||
Insert,
|
||||
Update,
|
||||
Delete
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,16 @@
|
||||
using System;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Persistence.UnitOfWork
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a Unit Of Work
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public interface IUnitOfWork<T> : IDisposable
|
||||
public interface IUnitOfWork
|
||||
{
|
||||
void RegisterAdded(IEntity entity, IUnitOfWorkRepository repository);
|
||||
void RegisterChanged(IEntity entity, IUnitOfWorkRepository repository);
|
||||
void RegisterRemoved(IEntity entity, IUnitOfWorkRepository repository);
|
||||
void Commit();
|
||||
T Storage { get; }//TODO This won't work! Need to change it
|
||||
object Key { get; }
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,8 @@
|
||||
/// <summary>
|
||||
/// Defines a Unit of Work Provider
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public interface IUnitOfWorkProvider<T>
|
||||
public interface IUnitOfWorkProvider
|
||||
{
|
||||
IUnitOfWork<T> GetUnitOfWork();
|
||||
IUnitOfWork GetUnitOfWork();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Persistence.UnitOfWork
|
||||
{
|
||||
public interface IUnitOfWorkRepository
|
||||
{
|
||||
void PersistNewItem(IEntity entity);
|
||||
void PersistUpdatedItem(IEntity entity);
|
||||
void PersistDeletedItem(IEntity entity);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,142 @@
|
||||
using Umbraco.Core.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Persistence.UnitOfWork
|
||||
{
|
||||
internal class PetaPocoUnitOfWork : IUnitOfWork<Database>
|
||||
/// <summary>
|
||||
/// Represents the Unit of Work implementation for PetaPoco
|
||||
/// </summary>
|
||||
internal class PetaPocoUnitOfWork : IUnitOfWork
|
||||
{
|
||||
private readonly Transaction _petaTransaction;
|
||||
private readonly Database _storage;
|
||||
private Guid _key;
|
||||
private List<Operation> _operations;
|
||||
|
||||
public PetaPocoUnitOfWork()
|
||||
{
|
||||
var connectionString = GlobalSettings.DbDsn;
|
||||
_storage = new Database(connectionString);
|
||||
_petaTransaction = new Transaction(_storage);
|
||||
_key = Guid.NewGuid();
|
||||
_operations = new List<Operation>();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
/// <summary>
|
||||
/// Registers an <see cref="IEntity" /> instance to be added through this <see cref="UnitOfWork" />
|
||||
/// </summary>
|
||||
/// <param name="entity">The <see cref="IEntity" /></param>
|
||||
/// <param name="repository">The <see cref="IUnitOfWorkRepository" /> participating in the transaction</param>
|
||||
public void RegisterAdded(IEntity entity, IUnitOfWorkRepository repository)
|
||||
{
|
||||
_petaTransaction.Dispose();
|
||||
_operations.Add(
|
||||
new Operation
|
||||
{
|
||||
Entity = entity,
|
||||
ProcessDate = DateTime.Now,
|
||||
Repository = repository,
|
||||
Type = TransactionType.Insert
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers an <see cref="IEntity" /> instance to be changed through this <see cref="UnitOfWork" />
|
||||
/// </summary>
|
||||
/// <param name="entity">The <see cref="IEntity" /></param>
|
||||
/// <param name="repository">The <see cref="IUnitOfWorkRepository" /> participating in the transaction</param>
|
||||
public void RegisterChanged(IEntity entity, IUnitOfWorkRepository repository)
|
||||
{
|
||||
_operations.Add(
|
||||
new Operation
|
||||
{
|
||||
Entity = entity,
|
||||
ProcessDate = DateTime.Now,
|
||||
Repository = repository,
|
||||
Type = TransactionType.Update
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers an <see cref="IEntity" /> instance to be removed through this <see cref="UnitOfWork" />
|
||||
/// </summary>
|
||||
/// <param name="entity">The <see cref="IEntity" /></param>
|
||||
/// <param name="repository">The <see cref="IUnitOfWorkRepository" /> participating in the transaction</param>
|
||||
public void RegisterRemoved(IEntity entity, IUnitOfWorkRepository repository)
|
||||
{
|
||||
_operations.Add(
|
||||
new Operation
|
||||
{
|
||||
Entity = entity,
|
||||
ProcessDate = DateTime.Now,
|
||||
Repository = repository,
|
||||
Type = TransactionType.Delete
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Commits all batched changes within the scope of a PetaPoco transaction <see cref="Transaction"/>
|
||||
/// </summary>
|
||||
public void Commit()
|
||||
{
|
||||
_petaTransaction.Complete();
|
||||
using(Transaction transaction = DatabaseFactory.Current.Database.GetTransaction())
|
||||
{
|
||||
foreach (var operation in _operations.OrderBy(o => o.ProcessDate))
|
||||
{
|
||||
switch (operation.Type)
|
||||
{
|
||||
case TransactionType.Insert:
|
||||
operation.Repository.PersistNewItem(operation.Entity);
|
||||
break;
|
||||
case TransactionType.Delete:
|
||||
operation.Repository.PersistDeletedItem(operation.Entity);
|
||||
break;
|
||||
case TransactionType.Update:
|
||||
operation.Repository.PersistUpdatedItem(operation.Entity);
|
||||
break;
|
||||
}
|
||||
}
|
||||
transaction.Complete();
|
||||
}
|
||||
|
||||
// Clear everything
|
||||
_operations.Clear();
|
||||
_key = Guid.NewGuid();
|
||||
}
|
||||
|
||||
public Database Storage
|
||||
public object Key
|
||||
{
|
||||
get { return _storage; }
|
||||
get { return _key; }
|
||||
}
|
||||
|
||||
#region Operation
|
||||
|
||||
/// <summary>
|
||||
/// Provides a snapshot of an entity and the repository reference it belongs to.
|
||||
/// </summary>
|
||||
private sealed class Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the entity.
|
||||
/// </summary>
|
||||
/// <value>The entity.</value>
|
||||
public IEntity Entity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the process date.
|
||||
/// </summary>
|
||||
/// <value>The process date.</value>
|
||||
public DateTime ProcessDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the repository.
|
||||
/// </summary>
|
||||
/// <value>The repository.</value>
|
||||
public IUnitOfWorkRepository Repository { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of operation.
|
||||
/// </summary>
|
||||
/// <value>The type of operation.</value>
|
||||
public TransactionType Type { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,14 @@
|
||||
namespace Umbraco.Core.Persistence.UnitOfWork
|
||||
{
|
||||
internal class PetaPocoUnitOfWorkProvider : IUnitOfWorkProvider<Database>
|
||||
internal class PetaPocoUnitOfWorkProvider : IUnitOfWorkProvider
|
||||
{
|
||||
public IUnitOfWork<Database> GetUnitOfWork()
|
||||
#region Implementation of IUnitOfWorkProvider
|
||||
|
||||
public IUnitOfWork GetUnitOfWork()
|
||||
{
|
||||
return new PetaPocoUnitOfWork();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -91,7 +91,10 @@
|
||||
<Compile Include="Persistence\Caching\InMemoryCacheProvider.cs" />
|
||||
<Compile Include="Persistence\Caching\IRepositoryCacheProvider.cs" />
|
||||
<Compile Include="Persistence\Caching\RuntimeCacheProvider.cs" />
|
||||
<Compile Include="Persistence\Factories\ContentFactory.cs" />
|
||||
<Compile Include="Persistence\DatabaseFactory.cs" />
|
||||
<Compile Include="Persistence\Factories\EntityFactory.cs" />
|
||||
<Compile Include="Persistence\Factories\IEntityFactory.cs" />
|
||||
<Compile Include="Persistence\Factories\PropertyFactory.cs" />
|
||||
<Compile Include="Persistence\Mappers\ModelDtoMapper.cs" />
|
||||
<Compile Include="Persistence\Querying\ExpressionHelper.cs" />
|
||||
<Compile Include="Persistence\Querying\IQuery.cs" />
|
||||
@@ -102,10 +105,13 @@
|
||||
<Compile Include="Persistence\Repositories\IContentTypeRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\IRepository.cs" />
|
||||
<Compile Include="Persistence\Relators\TabPropertyTypeRelator.cs" />
|
||||
<Compile Include="Persistence\Repositories\Repository.cs" />
|
||||
<Compile Include="Persistence\Repositories\PetaPocoRepositoryBase.cs" />
|
||||
<Compile Include="Persistence\Repositories\RepositoryBase.cs" />
|
||||
<Compile Include="Persistence\RepositoryResolver.cs" />
|
||||
<Compile Include="Persistence\TransactionType.cs" />
|
||||
<Compile Include="Persistence\UnitOfWork\IUnitOfWork.cs" />
|
||||
<Compile Include="Persistence\UnitOfWork\IUnitOfWorkProvider.cs" />
|
||||
<Compile Include="Persistence\UnitOfWork\IUnitOfWorkRepository.cs" />
|
||||
<Compile Include="Persistence\UnitOfWork\PetaPocoUnitOfWork.cs" />
|
||||
<Compile Include="Persistence\UnitOfWork\PetaPocoUnitOfWorkProvider.cs" />
|
||||
<Compile Include="PropertyEditors\Attributes\PropertyEditorAttribute.cs" />
|
||||
|
||||
Reference in New Issue
Block a user