Moves the CRUD logic from the media service to the media repo for dealing with content xml items and ensures it's done in the same transaction, streamlines how this process is done between the content, media, member services, adds test for it.
This commit is contained in:
@@ -8,12 +8,13 @@ namespace Umbraco.Core.Models
|
||||
/// Used in content/media/member repositories in order to add this type of entity to the persisted collection to be saved
|
||||
/// in a single transaction during saving an entity
|
||||
/// </summary>
|
||||
internal class ContentXmlEntity : IAggregateRoot
|
||||
internal class ContentXmlEntity<TContent> : IAggregateRoot
|
||||
where TContent : IContentBase
|
||||
{
|
||||
private readonly bool _entityExists;
|
||||
private readonly Func<XElement> _xml;
|
||||
private readonly Func<TContent, XElement> _xml;
|
||||
|
||||
public ContentXmlEntity(bool entityExists, IContentBase content, Func<XElement> xml)
|
||||
public ContentXmlEntity(bool entityExists, TContent content, Func<TContent, XElement> xml)
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException("content");
|
||||
_entityExists = entityExists;
|
||||
@@ -23,9 +24,9 @@ namespace Umbraco.Core.Models
|
||||
|
||||
public XElement Xml
|
||||
{
|
||||
get { return _xml(); }
|
||||
get { return _xml(Content); }
|
||||
}
|
||||
public IContentBase Content { get; private set; }
|
||||
public TContent Content { get; private set; }
|
||||
|
||||
public int Id
|
||||
{
|
||||
@@ -44,7 +45,7 @@ namespace Umbraco.Core.Models
|
||||
|
||||
public object DeepClone()
|
||||
{
|
||||
var clone = (ContentXmlEntity)MemberwiseClone();
|
||||
var clone = (ContentXmlEntity<TContent>)MemberwiseClone();
|
||||
//Automatically deep clone ref properties that are IDeepCloneable
|
||||
DeepCloneHelper.DeepCloneRefProperties(this, clone);
|
||||
return clone;
|
||||
|
||||
@@ -13,6 +13,7 @@ using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.Caching;
|
||||
using Umbraco.Core.Persistence.Factories;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
@@ -26,7 +27,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
private readonly ITemplateRepository _templateRepository;
|
||||
private readonly CacheHelper _cacheHelper;
|
||||
private readonly ContentPreviewRepository _contentPreviewRepository;
|
||||
private readonly ContentXmlRepository _contentXmlRepository;
|
||||
private readonly ContentXmlRepository<IContent> _contentXmlRepository;
|
||||
|
||||
public ContentRepository(IDatabaseUnitOfWork work, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, CacheHelper cacheHelper)
|
||||
: base(work)
|
||||
@@ -35,7 +36,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
_templateRepository = templateRepository;
|
||||
_cacheHelper = cacheHelper;
|
||||
_contentPreviewRepository = new ContentPreviewRepository(work, NullCacheProvider.Current);
|
||||
_contentXmlRepository = new ContentXmlRepository(work, NullCacheProvider.Current);
|
||||
_contentXmlRepository = new ContentXmlRepository<IContent>(work, NullCacheProvider.Current);
|
||||
|
||||
EnsureUniqueNaming = true;
|
||||
}
|
||||
@@ -47,7 +48,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
_templateRepository = templateRepository;
|
||||
_cacheHelper = cacheHelper;
|
||||
_contentPreviewRepository = new ContentPreviewRepository(work, NullCacheProvider.Current);
|
||||
_contentXmlRepository = new ContentXmlRepository(work, NullCacheProvider.Current);
|
||||
_contentXmlRepository = new ContentXmlRepository<IContent>(work, NullCacheProvider.Current);
|
||||
|
||||
EnsureUniqueNaming = true;
|
||||
}
|
||||
@@ -566,18 +567,20 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// Adds/updates content/published xml
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
public void AddOrUpdateContentXml(IContent content, Func<XElement> xml)
|
||||
/// <param name="xml"></param>
|
||||
public void AddOrUpdateContentXml(IContent content, Func<IContent, XElement> xml)
|
||||
{
|
||||
var contentExists = Database.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsContentXml WHERE nodeId = @Id", new { Id = content.Id }) != 0;
|
||||
|
||||
_contentXmlRepository.AddOrUpdate(new ContentXmlEntity(contentExists, content, xml));
|
||||
_contentXmlRepository.AddOrUpdate(new ContentXmlEntity<IContent>(contentExists, content, xml));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds/updates preview xml
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
public void AddOrUpdatePreviewXml(IContent content, Func<XElement> xml)
|
||||
/// <param name="xml"></param>
|
||||
public void AddOrUpdatePreviewXml(IContent content, Func<IContent, XElement> xml)
|
||||
{
|
||||
var previewExists =
|
||||
Database.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsPreviewXml WHERE nodeId = @Id AND versionId = @Version",
|
||||
@@ -585,7 +588,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
_contentPreviewRepository.AddOrUpdate(new ContentPreviewEntity(previewExists, content, xml));
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@@ -653,9 +656,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// Used content repository in order to add an entity to the persisted collection to be saved
|
||||
/// in a single transaction during saving an entity
|
||||
/// </summary>
|
||||
private class ContentPreviewEntity : ContentXmlEntity
|
||||
private class ContentPreviewEntity : ContentXmlEntity<IContent>
|
||||
{
|
||||
public ContentPreviewEntity(bool previewExists, IContentBase content, Func<XElement> xml)
|
||||
public ContentPreviewEntity(bool previewExists, IContent content, Func<IContent, XElement> xml)
|
||||
: base(previewExists, content, xml)
|
||||
{
|
||||
Version = content.Version;
|
||||
|
||||
@@ -12,7 +12,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <summary>
|
||||
/// Internal class to handle content/published xml insert/update based on standard principles and units of work with transactions
|
||||
/// </summary>
|
||||
internal class ContentXmlRepository : PetaPocoRepositoryBase<int, ContentXmlEntity>
|
||||
internal class ContentXmlRepository<TContent> : PetaPocoRepositoryBase<int, ContentXmlEntity<TContent>>
|
||||
where TContent : IContentBase
|
||||
{
|
||||
public ContentXmlRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache)
|
||||
: base(work, cache)
|
||||
@@ -20,17 +21,17 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
|
||||
#region Not implemented (don't need to for the purposes of this repo)
|
||||
protected override ContentXmlEntity PerformGet(int id)
|
||||
protected override ContentXmlEntity<TContent> PerformGet(int id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override IEnumerable<ContentXmlEntity> PerformGetAll(params int[] ids)
|
||||
protected override IEnumerable<ContentXmlEntity<TContent>> PerformGetAll(params int[] ids)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override IEnumerable<ContentXmlEntity> PerformGetByQuery(IQuery<ContentXmlEntity> query)
|
||||
protected override IEnumerable<ContentXmlEntity<TContent>> PerformGetByQuery(IQuery<ContentXmlEntity<TContent>> query)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
@@ -55,13 +56,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
protected override void PersistDeletedItem(ContentXmlEntity entity)
|
||||
protected override void PersistDeletedItem(ContentXmlEntity<TContent> entity)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected override void PersistNewItem(ContentXmlEntity entity)
|
||||
protected override void PersistNewItem(ContentXmlEntity<TContent> entity)
|
||||
{
|
||||
if (entity.Content.HasIdentity == false)
|
||||
{
|
||||
@@ -72,7 +73,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
Database.Insert(poco);
|
||||
}
|
||||
|
||||
protected override void PersistUpdatedItem(ContentXmlEntity entity)
|
||||
protected override void PersistUpdatedItem(ContentXmlEntity<TContent> entity)
|
||||
{
|
||||
if (entity.Content.HasIdentity == false)
|
||||
{
|
||||
|
||||
@@ -44,13 +44,14 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="xml"></param>
|
||||
void AddOrUpdateContentXml(IContent content, Func<XElement> xml);
|
||||
void AddOrUpdateContentXml(IContent content, Func<IContent, XElement> xml);
|
||||
|
||||
/// <summary>
|
||||
/// Used to add/update preview xml for the content item
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="xml"></param>
|
||||
void AddOrUpdatePreviewXml(IContent content, Func<XElement> xml);
|
||||
void AddOrUpdatePreviewXml(IContent content, Func<IContent, XElement> xml);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,18 @@
|
||||
using Umbraco.Core.Models;
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public interface IMediaRepository : IRepositoryVersionable<int, IMedia>
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Used to add/update published xml for the media item
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="xml"></param>
|
||||
void AddOrUpdateContentXml(IMedia content, Func<IMedia, XElement> xml);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -20,11 +21,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
internal class MediaRepository : VersionableRepositoryBase<int, IMedia>, IMediaRepository
|
||||
{
|
||||
private readonly IMediaTypeRepository _mediaTypeRepository;
|
||||
private readonly ContentXmlRepository<IMedia> _contentXmlRepository;
|
||||
|
||||
public MediaRepository(IDatabaseUnitOfWork work, IMediaTypeRepository mediaTypeRepository)
|
||||
: base(work)
|
||||
{
|
||||
_mediaTypeRepository = mediaTypeRepository;
|
||||
_contentXmlRepository = new ContentXmlRepository<IMedia>(work, NullCacheProvider.Current);
|
||||
|
||||
EnsureUniqueNaming = true;
|
||||
}
|
||||
@@ -33,6 +36,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
: base(work, cache)
|
||||
{
|
||||
_mediaTypeRepository = mediaTypeRepository;
|
||||
_contentXmlRepository = new ContentXmlRepository<IMedia>(work, NullCacheProvider.Current);
|
||||
|
||||
EnsureUniqueNaming = true;
|
||||
}
|
||||
@@ -174,6 +178,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return media;
|
||||
}
|
||||
|
||||
public void AddOrUpdateContentXml(IMedia content, Func<IMedia, XElement> xml)
|
||||
{
|
||||
var contentExists = Database.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsContentXml WHERE nodeId = @Id", new { Id = content.Id }) != 0;
|
||||
|
||||
_contentXmlRepository.AddOrUpdate(new ContentXmlEntity<IMedia>(contentExists, content, xml));
|
||||
}
|
||||
|
||||
protected override void PerformDeleteVersion(int id, Guid versionId)
|
||||
{
|
||||
Database.Delete<PreviewXmlDto>("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
|
||||
|
||||
@@ -1350,15 +1350,13 @@ namespace Umbraco.Core.Services
|
||||
repository.AddOrUpdate(content);
|
||||
|
||||
//Generate a new preview
|
||||
var local = content;
|
||||
repository.AddOrUpdatePreviewXml(content, () => _entitySerializer.Serialize(this, _dataTypeService, local));
|
||||
repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, c));
|
||||
}
|
||||
|
||||
foreach (var content in shouldBePublished)
|
||||
{
|
||||
//Create and Save ContentXml DTO
|
||||
var local = content;
|
||||
repository.AddOrUpdateContentXml(content, () => _entitySerializer.Serialize(this, _dataTypeService, local));
|
||||
repository.AddOrUpdateContentXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, c));
|
||||
}
|
||||
|
||||
uow.Commit();
|
||||
@@ -1511,6 +1509,8 @@ namespace Umbraco.Core.Services
|
||||
//TODO: WE should make a base class for ContentService and MediaService to share!
|
||||
// currently we have this logic duplicated (nearly the same) for media types and soon to be member types
|
||||
|
||||
//TODO: This needs to be put into the ContentRepository, all CUD logic!
|
||||
|
||||
/// <summary>
|
||||
/// Rebuilds all xml content in the cmsContentXml table for all documents
|
||||
/// </summary>
|
||||
@@ -1776,13 +1776,12 @@ namespace Umbraco.Core.Services
|
||||
repository.AddOrUpdate(content);
|
||||
|
||||
//Generate a new preview
|
||||
var local = content;
|
||||
repository.AddOrUpdatePreviewXml(content, () => _entitySerializer.Serialize(this, _dataTypeService, local));
|
||||
repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, c));
|
||||
|
||||
if (published)
|
||||
{
|
||||
//Content Xml
|
||||
repository.AddOrUpdateContentXml(content, () => _entitySerializer.Serialize(this, _dataTypeService, local));
|
||||
repository.AddOrUpdateContentXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, c));
|
||||
}
|
||||
|
||||
uow.Commit();
|
||||
@@ -1844,8 +1843,7 @@ namespace Umbraco.Core.Services
|
||||
repository.AddOrUpdate(content);
|
||||
|
||||
//Generate a new preview
|
||||
var local = content;
|
||||
repository.AddOrUpdatePreviewXml(content, () => _entitySerializer.Serialize(this, _dataTypeService, local));
|
||||
repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, c));
|
||||
|
||||
uow.Commit();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
//TODO: Move the rest of the logic for the PackageService.Export methods to here!
|
||||
|
||||
/// <summary>
|
||||
/// A helper class to serialize entities to XML
|
||||
/// </summary>
|
||||
|
||||
@@ -156,10 +156,10 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
media.CreatorId = userId;
|
||||
repository.AddOrUpdate(media);
|
||||
uow.Commit();
|
||||
|
||||
var xml = _entitySerializer.Serialize(this, _dataTypeService, media);
|
||||
CreateAndSaveMediaXml(xml, media.Id, uow.Database);
|
||||
repository.AddOrUpdateContentXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, m));
|
||||
|
||||
uow.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,10 +211,8 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
media.CreatorId = userId;
|
||||
repository.AddOrUpdate(media);
|
||||
repository.AddOrUpdateContentXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, m));
|
||||
uow.Commit();
|
||||
|
||||
var xml = _entitySerializer.Serialize(this, _dataTypeService, media);
|
||||
CreateAndSaveMediaXml(xml, media.Id, uow.Database);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -809,10 +807,9 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
media.CreatorId = userId;
|
||||
repository.AddOrUpdate(media);
|
||||
uow.Commit();
|
||||
repository.AddOrUpdateContentXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, m));
|
||||
|
||||
var xml = _entitySerializer.Serialize(this, _dataTypeService, media);
|
||||
CreateAndSaveMediaXml(xml, media.Id, uow.Database);
|
||||
uow.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -847,16 +844,11 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
media.CreatorId = userId;
|
||||
repository.AddOrUpdate(media);
|
||||
repository.AddOrUpdateContentXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, m));
|
||||
}
|
||||
|
||||
//commit the whole lot in one go
|
||||
uow.Commit();
|
||||
|
||||
foreach (var media in asArray)
|
||||
{
|
||||
var xml = _entitySerializer.Serialize(this, _dataTypeService, media);
|
||||
CreateAndSaveMediaXml(xml, media.Id, uow.Database);
|
||||
}
|
||||
}
|
||||
|
||||
if (raiseEvents)
|
||||
@@ -884,8 +876,6 @@ namespace Umbraco.Core.Services
|
||||
return false;
|
||||
}
|
||||
|
||||
var shouldBeCached = new List<IMedia>();
|
||||
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
@@ -907,17 +897,10 @@ namespace Umbraco.Core.Services
|
||||
i++;
|
||||
|
||||
repository.AddOrUpdate(media);
|
||||
shouldBeCached.Add(media);
|
||||
repository.AddOrUpdateContentXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, m));
|
||||
}
|
||||
|
||||
uow.Commit();
|
||||
|
||||
foreach (var content in shouldBeCached)
|
||||
{
|
||||
//Create and Save ContentXml DTO
|
||||
var xml = _entitySerializer.Serialize(this, _dataTypeService, content);
|
||||
CreateAndSaveMediaXml(xml, content.Id, uow.Database);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -929,6 +912,8 @@ namespace Umbraco.Core.Services
|
||||
return true;
|
||||
}
|
||||
|
||||
//TODO: This needs to be put into the MediaRepository, all CUD logic!
|
||||
|
||||
/// <summary>
|
||||
/// Rebuilds all xml content in the cmsContentXml table for all media
|
||||
/// </summary>
|
||||
@@ -1052,12 +1037,12 @@ namespace Umbraco.Core.Services
|
||||
return list;
|
||||
}
|
||||
|
||||
private void CreateAndSaveMediaXml(XElement xml, int id, UmbracoDatabase db)
|
||||
{
|
||||
var poco = new ContentXmlDto { NodeId = id, Xml = xml.ToString(SaveOptions.None) };
|
||||
var exists = db.FirstOrDefault<ContentXmlDto>("WHERE nodeId = @Id", new { Id = id }) != null;
|
||||
int result = exists ? db.Update(poco) : Convert.ToInt32(db.Insert(poco));
|
||||
}
|
||||
//private void CreateAndSaveMediaXml(XElement xml, int id, UmbracoDatabase db)
|
||||
//{
|
||||
// var poco = new ContentXmlDto { NodeId = id, Xml = xml.ToString(SaveOptions.None) };
|
||||
// var exists = db.FirstOrDefault<ContentXmlDto>("WHERE nodeId = @Id", new { Id = id }) != null;
|
||||
// int result = exists ? db.Update(poco) : Convert.ToInt32(db.Insert(poco));
|
||||
//}
|
||||
|
||||
private IMediaType FindMediaTypeByAlias(string mediaTypeAlias)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user