Adds the foundation for the repository implementation with abstract Repository, Unit Of Work and Cache provider.
Adding the Query object implementation. Adds the ModelDtoMapper, which is still a WIP. Adds the initial implementation of the IContentRepository with dependencies.
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Caching
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the implementation of a Cache Provider intented to back a repository
|
||||
/// </summary>
|
||||
internal interface IRepositoryCacheProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets an Entity from the cache by Type and Id
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
IEntity GetById(Type type, Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an Entity from the cache by Type and Ids
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="ids"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<IEntity> GetByIds(Type type, List<Guid> ids);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all Entities of specified type
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<IEntity> GetAllByType(Type type);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the Entity
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="entity"></param>
|
||||
void Save(Type type, IEntity entity);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the Entity from the cache
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="entity"></param>
|
||||
void Delete(Type type, IEntity entity);
|
||||
}
|
||||
}
|
||||
114
src/Umbraco.Core/Persistence/Caching/InMemoryCacheProvider.cs
Normal file
114
src/Umbraco.Core/Persistence/Caching/InMemoryCacheProvider.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Caching
|
||||
{
|
||||
/// <summary>
|
||||
/// The InMemory registry looks up objects in an in-memory dictionary for fast retrival
|
||||
/// </summary>
|
||||
internal class InMemoryCacheProvider : IRepositoryCacheProvider
|
||||
{
|
||||
#region Singleton
|
||||
private static volatile InMemoryCacheProvider _instance;
|
||||
private static readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim();
|
||||
|
||||
private InMemoryCacheProvider() { }
|
||||
|
||||
public static InMemoryCacheProvider Current
|
||||
{
|
||||
get
|
||||
{
|
||||
using (new WriteLock(Lock))
|
||||
{
|
||||
if (_instance == null) _instance = new InMemoryCacheProvider();
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
private readonly ConcurrentDictionary<string, IEntity> _cache = new ConcurrentDictionary<string, IEntity>();
|
||||
|
||||
/// <summary>
|
||||
/// Retrives an object of the specified type by its Id
|
||||
/// </summary>
|
||||
/// <param name="type">The type of the object to retrive, which implements <see cref="IEntity"/></param>
|
||||
/// <param name="id">The Guid Id of the Object to retrive</param>
|
||||
/// <returns></returns>
|
||||
public IEntity GetById(Type type, Guid id)
|
||||
{
|
||||
var compositeKey = GetCompositeId(type, id);
|
||||
var containsKey = _cache.ContainsKey(compositeKey);
|
||||
if (containsKey)
|
||||
{
|
||||
return _cache[compositeKey];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrives objects of the specified type by their Ids
|
||||
/// </summary>
|
||||
/// <param name="type">The type of the objects to retrive, which implements <see cref="IEntity"/></param>
|
||||
/// <param name="ids">The Guid Ids of the Objects to retrive</param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<IEntity> GetByIds(Type type, List<Guid> ids)
|
||||
{
|
||||
var list = (from id in ids
|
||||
select GetCompositeId(type, id)
|
||||
into key
|
||||
let containsKey = _cache.ContainsKey(key)
|
||||
where containsKey
|
||||
select _cache[key]).ToList();
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrives all objects of the specified type
|
||||
/// </summary>
|
||||
/// <param name="type">The type of the objects to retrive, which implements <see cref="IEntity"/></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<IEntity> GetAllByType(Type type)
|
||||
{
|
||||
var list = _cache.Keys.Where(key => key.Contains(type.Name)).Select(key => _cache[key]).ToList();
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves an object in the registry cache
|
||||
/// </summary>
|
||||
/// <param name="type"> </param>
|
||||
/// <param name="entity"></param>
|
||||
public void Save(Type type, IEntity entity)
|
||||
{
|
||||
_cache.AddOrUpdate(GetCompositeId(type, entity.Key), entity, (x, y) => entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes an object from the registry cache
|
||||
/// </summary>
|
||||
/// <param name="type"> </param>
|
||||
/// <param name="entity"></param>
|
||||
public void Delete(Type type, IEntity entity)
|
||||
{
|
||||
IEntity entity1;
|
||||
bool result = _cache.TryRemove(GetCompositeId(type, entity.Key), out entity1);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_cache.Clear();
|
||||
}
|
||||
|
||||
private string GetCompositeId(Type type, Guid id)
|
||||
{
|
||||
return string.Format("{0}-{1}", type.Name, id.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
93
src/Umbraco.Core/Persistence/Caching/RuntimeCacheProvider.cs
Normal file
93
src/Umbraco.Core/Persistence/Caching/RuntimeCacheProvider.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Caching;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Caching
|
||||
{
|
||||
/// <summary>
|
||||
/// The Runtime Cache provider looks up objects in the Runtime cache for fast retrival
|
||||
/// </summary>
|
||||
internal sealed class RuntimeCacheProvider : IRepositoryCacheProvider
|
||||
{
|
||||
#region Singleton
|
||||
private static volatile RuntimeCacheProvider _instance;
|
||||
private static readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim();
|
||||
|
||||
private RuntimeCacheProvider() { }
|
||||
|
||||
public static RuntimeCacheProvider Current
|
||||
{
|
||||
get
|
||||
{
|
||||
using (new WriteLock(Lock))
|
||||
{
|
||||
if (_instance == null) _instance = new RuntimeCacheProvider();
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
private ObjectCache _memoryCache = new MemoryCache("in-memory");
|
||||
private ConcurrentDictionary<string, string> _keyTracker = new ConcurrentDictionary<string, string>();
|
||||
|
||||
public IEntity GetById(Type type, Guid id)
|
||||
{
|
||||
var key = GetCompositeId(type, id);
|
||||
var item = _memoryCache.Get(key);
|
||||
return item as IEntity;
|
||||
}
|
||||
|
||||
public IEnumerable<IEntity> GetByIds(Type type, List<Guid> ids)
|
||||
{
|
||||
foreach (var guid in ids)
|
||||
{
|
||||
yield return _memoryCache.Get(GetCompositeId(type, guid)) as IEntity;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<IEntity> GetAllByType(Type type)
|
||||
{
|
||||
foreach (var key in _keyTracker.Keys)
|
||||
{
|
||||
if (key.StartsWith(type.Name))
|
||||
{
|
||||
yield return _memoryCache.Get(key) as IEntity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Save(Type type, IEntity entity)
|
||||
{
|
||||
var key = GetCompositeId(type, entity.Key);
|
||||
var exists = _memoryCache.GetCacheItem(key) != null;
|
||||
|
||||
_keyTracker.TryAdd(key, key);
|
||||
if (exists)
|
||||
{
|
||||
_memoryCache.Set(key, entity, new CacheItemPolicy { SlidingExpiration = TimeSpan.FromMinutes(5) });
|
||||
return;
|
||||
}
|
||||
|
||||
_memoryCache.Add(key, entity, new CacheItemPolicy { SlidingExpiration = TimeSpan.FromMinutes(5) });
|
||||
}
|
||||
|
||||
public void Delete(Type type, IEntity entity)
|
||||
{
|
||||
string throwaway = null;
|
||||
var key = GetCompositeId(type, entity.Key);
|
||||
var keyBeSure = _keyTracker.TryGetValue(key, out throwaway);
|
||||
object itemRemoved = _memoryCache.Remove(key);
|
||||
_keyTracker.TryRemove(key, out throwaway);
|
||||
}
|
||||
|
||||
private string GetCompositeId(Type type, Guid id)
|
||||
{
|
||||
return string.Format("{0}-{1}", type.Name, id.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
164
src/Umbraco.Core/Persistence/Factories/ContentFactory.cs
Normal file
164
src/Umbraco.Core/Persistence/Factories/ContentFactory.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
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,
|
||||
CreatedDate = documentDto.ContentVersionDto.ContentDto.NodeDto.CreateDate,
|
||||
ModifiedDate = 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.CreatedDate,
|
||||
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.CreatedDate,
|
||||
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.ModifiedDate,
|
||||
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.ModifiedDate,
|
||||
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 };
|
||||
/*if (property.Value is IEditorModel)
|
||||
{
|
||||
var result = service.ToStream(property.Value);
|
||||
dto.Text = result.ResultStream.ToJsonString();
|
||||
}*/
|
||||
if (property.Value is int)
|
||||
{
|
||||
dto.Integer = int.Parse(property.Value.ToString());
|
||||
}
|
||||
else if (property.Value is DateTime)
|
||||
{
|
||||
dto.Date = DateTime.Parse(property.Value.ToString());
|
||||
}
|
||||
else if (property.Value is string)
|
||||
{
|
||||
dto.Text = property.Value.ToString();
|
||||
}
|
||||
else if (property.Value != null)
|
||||
{
|
||||
dto.VarChar = property.Value.ToString();//TODO Check how/when NVarChar is actually set/used
|
||||
}
|
||||
|
||||
propertyDataDtos.Add(dto);
|
||||
}
|
||||
return propertyDataDtos;
|
||||
}
|
||||
}
|
||||
}
|
||||
86
src/Umbraco.Core/Persistence/Mappers/ModelDtoMapper.cs
Normal file
86
src/Umbraco.Core/Persistence/Mappers/ModelDtoMapper.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Mappers
|
||||
{
|
||||
internal class ModelDtoMapper : IMapper
|
||||
{
|
||||
public void GetTableInfo(Type t, TableInfo ti)
|
||||
{ }
|
||||
|
||||
public bool MapPropertyToColumn(PropertyInfo pi, ref string columnName, ref bool resultColumn)
|
||||
{
|
||||
if (pi.DeclaringType == typeof(Content) || pi.DeclaringType == typeof(IContent))
|
||||
{
|
||||
switch (pi.Name)
|
||||
{
|
||||
case "Trashed":
|
||||
columnName = "[umbracoNode].[trashed]";
|
||||
return true;
|
||||
case "ParentId":
|
||||
columnName = "[umbracoNode].[parentID]";
|
||||
return true;
|
||||
case "UserId":
|
||||
columnName = "[umbracoNode].[nodeUser]";
|
||||
return true;
|
||||
case "Level":
|
||||
columnName = "[umbracoNode].[level]";
|
||||
return true;
|
||||
case "Path":
|
||||
columnName = "[umbracoNode].[path]";
|
||||
return true;
|
||||
case "SortOrder":
|
||||
columnName = "[umbracoNode].[sortOrder]";
|
||||
return true;
|
||||
case "NodeId":
|
||||
columnName = "[umbracoNode].[id]";
|
||||
return true;
|
||||
case "Published":
|
||||
columnName = "[cmsDocument].[published]";
|
||||
return true;
|
||||
case "Key":
|
||||
columnName = "[umbracoNode].[uniqueID]";
|
||||
return true;
|
||||
case "CreatedDate":
|
||||
columnName = "[umbracoNode].[createDate]";
|
||||
return true;
|
||||
case "Name":
|
||||
columnName = "[umbracoNode].[text]";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (pi.DeclaringType == typeof(ContentType) || pi.DeclaringType == typeof(IContentType))
|
||||
{
|
||||
switch (pi.Name)
|
||||
{
|
||||
case "Alias":
|
||||
columnName = "[cmsContentType].[alias]";
|
||||
return true;
|
||||
case "Icon":
|
||||
columnName = "[cmsContentType].[icon]";
|
||||
return true;
|
||||
case "Thumbnail":
|
||||
columnName = "[cmsContentType].[thumbnail]";
|
||||
return true;
|
||||
case "Description":
|
||||
columnName = "[cmsContentType].[description]";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Func<object, object> GetFromDbConverter(PropertyInfo pi, Type sourceType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Func<object, object> GetToDbConverter(Type sourceType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
572
src/Umbraco.Core/Persistence/Querying/ExpressionHelper.cs
Normal file
572
src/Umbraco.Core/Persistence/Querying/ExpressionHelper.cs
Normal file
@@ -0,0 +1,572 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
internal class ExpressionHelper<T>
|
||||
{
|
||||
private string selectExpression = string.Empty;
|
||||
private string whereExpression;
|
||||
private string groupBy = string.Empty;
|
||||
private string havingExpression;
|
||||
private string orderBy = string.Empty;
|
||||
|
||||
IList<string> updateFields = new List<string>();
|
||||
IList<string> insertFields = new List<string>();
|
||||
|
||||
private string sep = string.Empty;
|
||||
private bool useFieldName = false;
|
||||
private Database.PocoData pd;
|
||||
|
||||
public ExpressionHelper()
|
||||
{
|
||||
Database.Mapper = new ModelDtoMapper();
|
||||
pd = new Database.PocoData(typeof(T));
|
||||
}
|
||||
|
||||
protected internal virtual string Visit(Expression exp)
|
||||
{
|
||||
|
||||
if (exp == null) return string.Empty;
|
||||
switch (exp.NodeType)
|
||||
{
|
||||
case ExpressionType.Lambda:
|
||||
return VisitLambda(exp as LambdaExpression);
|
||||
case ExpressionType.MemberAccess:
|
||||
return VisitMemberAccess(exp as MemberExpression);
|
||||
case ExpressionType.Constant:
|
||||
return VisitConstant(exp as ConstantExpression);
|
||||
case ExpressionType.Add:
|
||||
case ExpressionType.AddChecked:
|
||||
case ExpressionType.Subtract:
|
||||
case ExpressionType.SubtractChecked:
|
||||
case ExpressionType.Multiply:
|
||||
case ExpressionType.MultiplyChecked:
|
||||
case ExpressionType.Divide:
|
||||
case ExpressionType.Modulo:
|
||||
case ExpressionType.And:
|
||||
case ExpressionType.AndAlso:
|
||||
case ExpressionType.Or:
|
||||
case ExpressionType.OrElse:
|
||||
case ExpressionType.LessThan:
|
||||
case ExpressionType.LessThanOrEqual:
|
||||
case ExpressionType.GreaterThan:
|
||||
case ExpressionType.GreaterThanOrEqual:
|
||||
case ExpressionType.Equal:
|
||||
case ExpressionType.NotEqual:
|
||||
case ExpressionType.Coalesce:
|
||||
case ExpressionType.ArrayIndex:
|
||||
case ExpressionType.RightShift:
|
||||
case ExpressionType.LeftShift:
|
||||
case ExpressionType.ExclusiveOr:
|
||||
return "(" + VisitBinary(exp as BinaryExpression) + ")";
|
||||
case ExpressionType.Negate:
|
||||
case ExpressionType.NegateChecked:
|
||||
case ExpressionType.Not:
|
||||
case ExpressionType.Convert:
|
||||
case ExpressionType.ConvertChecked:
|
||||
case ExpressionType.ArrayLength:
|
||||
case ExpressionType.Quote:
|
||||
case ExpressionType.TypeAs:
|
||||
return VisitUnary(exp as UnaryExpression);
|
||||
case ExpressionType.Parameter:
|
||||
return VisitParameter(exp as ParameterExpression);
|
||||
case ExpressionType.Call:
|
||||
return VisitMethodCall(exp as MethodCallExpression);
|
||||
case ExpressionType.New:
|
||||
return VisitNew(exp as NewExpression);
|
||||
case ExpressionType.NewArrayInit:
|
||||
case ExpressionType.NewArrayBounds:
|
||||
return VisitNewArray(exp as NewArrayExpression);
|
||||
default:
|
||||
return exp.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string VisitLambda(LambdaExpression lambda)
|
||||
{
|
||||
if (lambda.Body.NodeType == ExpressionType.MemberAccess && sep == " ")
|
||||
{
|
||||
MemberExpression m = lambda.Body as MemberExpression;
|
||||
|
||||
if (m.Expression != null)
|
||||
{
|
||||
string r = VisitMemberAccess(m);
|
||||
return string.Format("{0}={1}", r, GetQuotedTrueValue());
|
||||
}
|
||||
|
||||
}
|
||||
return Visit(lambda.Body);
|
||||
}
|
||||
|
||||
protected virtual string VisitBinary(BinaryExpression b)
|
||||
{
|
||||
string left, right;
|
||||
var operand = BindOperant(b.NodeType); //sep= " " ??
|
||||
if (operand == "AND" || operand == "OR")
|
||||
{
|
||||
MemberExpression m = b.Left as MemberExpression;
|
||||
if (m != null && m.Expression != null)
|
||||
{
|
||||
string r = VisitMemberAccess(m);
|
||||
left = string.Format("{0}={1}", r, GetQuotedTrueValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
left = Visit(b.Left);
|
||||
}
|
||||
m = b.Right as MemberExpression;
|
||||
if (m != null && m.Expression != null)
|
||||
{
|
||||
string r = VisitMemberAccess(m);
|
||||
right = string.Format("{0}={1}", r, GetQuotedTrueValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
right = Visit(b.Right);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
left = Visit(b.Left);
|
||||
right = Visit(b.Right);
|
||||
}
|
||||
|
||||
if (operand == "=" && right == "null") operand = "is";
|
||||
else if (operand == "<>" && right == "null") operand = "is not";
|
||||
else if (operand == "=" || operand == "<>")
|
||||
{
|
||||
if (IsTrueExpression(right)) right = GetQuotedTrueValue();
|
||||
else if (IsFalseExpression(right)) right = GetQuotedFalseValue();
|
||||
|
||||
if (IsTrueExpression(left)) left = GetQuotedTrueValue();
|
||||
else if (IsFalseExpression(left)) left = GetQuotedFalseValue();
|
||||
|
||||
}
|
||||
|
||||
switch (operand)
|
||||
{
|
||||
case "MOD":
|
||||
case "COALESCE":
|
||||
return string.Format("{0}({1},{2})", operand, left, right);
|
||||
default:
|
||||
return left + sep + operand + sep + right;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string VisitMemberAccess(MemberExpression m)
|
||||
{
|
||||
if (m.Expression != null &&
|
||||
m.Expression.NodeType == ExpressionType.Parameter
|
||||
&& m.Expression.Type == typeof(T))
|
||||
{
|
||||
string field = GetFieldName(pd, m.Member.Name);
|
||||
return field;
|
||||
}
|
||||
|
||||
if (m.Expression != null && m.Expression.NodeType != ExpressionType.Constant)
|
||||
{
|
||||
Database.Mapper = new ModelDtoMapper();
|
||||
var def = new Database.PocoData(m.Expression.Type);
|
||||
string field = GetFieldName(def, m.Member.Name);
|
||||
return field;
|
||||
}
|
||||
|
||||
|
||||
var member = Expression.Convert(m, typeof(object));
|
||||
var lambda = Expression.Lambda<Func<object>>(member);
|
||||
var getter = lambda.Compile();
|
||||
object o = getter();
|
||||
return GetQuotedValue(o, o != null ? o.GetType() : null);
|
||||
|
||||
}
|
||||
|
||||
protected virtual string VisitNew(NewExpression nex)
|
||||
{
|
||||
// TODO : check !
|
||||
var member = Expression.Convert(nex, typeof(object));
|
||||
var lambda = Expression.Lambda<Func<object>>(member);
|
||||
try
|
||||
{
|
||||
var getter = lambda.Compile();
|
||||
object o = getter();
|
||||
return GetQuotedValue(o, o.GetType());
|
||||
}
|
||||
catch (System.InvalidOperationException)
|
||||
{ // FieldName ?
|
||||
List<Object> exprs = VisitExpressionList(nex.Arguments);
|
||||
var r = new StringBuilder();
|
||||
foreach (Object e in exprs)
|
||||
{
|
||||
r.AppendFormat("{0}{1}",
|
||||
r.Length > 0 ? "," : "",
|
||||
e);
|
||||
}
|
||||
return r.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected virtual string VisitParameter(ParameterExpression p)
|
||||
{
|
||||
return p.Name;
|
||||
}
|
||||
|
||||
protected virtual string VisitConstant(ConstantExpression c)
|
||||
{
|
||||
if (c.Value == null)
|
||||
return "null";
|
||||
else if (c.Value.GetType() == typeof(bool))
|
||||
{
|
||||
object o = GetQuotedValue(c.Value, c.Value.GetType());
|
||||
return string.Format("({0}={1})", GetQuotedTrueValue(), o);
|
||||
}
|
||||
else
|
||||
return GetQuotedValue(c.Value, c.Value.GetType());
|
||||
}
|
||||
|
||||
protected virtual string VisitUnary(UnaryExpression u)
|
||||
{
|
||||
switch (u.NodeType)
|
||||
{
|
||||
case ExpressionType.Not:
|
||||
string o = Visit(u.Operand);
|
||||
if (IsFieldName(o)) o = o + "=" + GetQuotedValue(true, typeof(bool));
|
||||
return "NOT (" + o + ")";
|
||||
default:
|
||||
return Visit(u.Operand);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected virtual string VisitMethodCall(MethodCallExpression m)
|
||||
{
|
||||
List<Object> args = this.VisitExpressionList(m.Arguments);
|
||||
|
||||
Object r;
|
||||
if (m.Object != null)
|
||||
r = Visit(m.Object);
|
||||
else
|
||||
{
|
||||
r = args[0];
|
||||
args.RemoveAt(0);
|
||||
}
|
||||
|
||||
switch (m.Method.Name)
|
||||
{
|
||||
case "ToUpper":
|
||||
return string.Format("upper({0})", r);
|
||||
case "ToLower":
|
||||
return string.Format("lower({0})", r);
|
||||
case "StartsWith":
|
||||
return string.Format("upper({0}) starting with {1} ", r, args[0].ToString().ToUpper());
|
||||
case "EndsWith":
|
||||
return string.Format("upper({0}) like '%{1}'", r, RemoveQuote(args[0].ToString()).ToUpper());
|
||||
case "Contains":
|
||||
return string.Format("upper({0}) like '%{1}%'", r, RemoveQuote(args[0].ToString()).ToUpper());
|
||||
case "Substring":
|
||||
var startIndex = Int32.Parse(args[0].ToString()) + 1;
|
||||
if (args.Count == 2)
|
||||
{
|
||||
var length = Int32.Parse(args[1].ToString());
|
||||
return string.Format("substring({0} from {1} for {2})",
|
||||
r,
|
||||
startIndex,
|
||||
length);
|
||||
}
|
||||
else
|
||||
return string.Format("substring({0} from {1})",
|
||||
r,
|
||||
startIndex);
|
||||
case "Round":
|
||||
case "Floor":
|
||||
case "Ceiling":
|
||||
case "Coalesce":
|
||||
case "Abs":
|
||||
case "Sum":
|
||||
return string.Format("{0}({1}{2})",
|
||||
m.Method.Name,
|
||||
r,
|
||||
args.Count == 1 ? string.Format(",{0}", args[0]) : "");
|
||||
case "Concat":
|
||||
var s = new StringBuilder();
|
||||
foreach (Object e in args)
|
||||
{
|
||||
s.AppendFormat(" || {0}", e);
|
||||
}
|
||||
return string.Format("{0}{1}", r, s.ToString());
|
||||
|
||||
case "In":
|
||||
|
||||
var member = Expression.Convert(m.Arguments[1], typeof(object));
|
||||
var lambda = Expression.Lambda<Func<object>>(member);
|
||||
var getter = lambda.Compile();
|
||||
|
||||
var inArgs = getter() as object[];
|
||||
|
||||
var sIn = new StringBuilder();
|
||||
foreach (Object e in inArgs)
|
||||
{
|
||||
if (e.GetType().ToString() != "System.Collections.Generic.List`1[System.Object]")
|
||||
{
|
||||
sIn.AppendFormat("{0}{1}",
|
||||
sIn.Length > 0 ? "," : "",
|
||||
GetQuotedValue(e, e.GetType()));
|
||||
}
|
||||
else
|
||||
{
|
||||
var listArgs = e as IList<Object>;
|
||||
foreach (Object el in listArgs)
|
||||
{
|
||||
sIn.AppendFormat("{0}{1}",
|
||||
sIn.Length > 0 ? "," : "",
|
||||
GetQuotedValue(el, el.GetType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string.Format("{0} {1} ({2})", r, m.Method.Name, sIn.ToString());
|
||||
case "Desc":
|
||||
return string.Format("{0} DESC", r);
|
||||
case "Alias":
|
||||
case "As":
|
||||
return string.Format("{0} As {1}", r,
|
||||
GetQuotedColumnName(RemoveQuoteFromAlias(RemoveQuote(args[0].ToString()))));
|
||||
case "ToString":
|
||||
return r.ToString();
|
||||
default:
|
||||
var s2 = new StringBuilder();
|
||||
foreach (Object e in args)
|
||||
{
|
||||
s2.AppendFormat(",{0}", GetQuotedValue(e, e.GetType()));
|
||||
}
|
||||
return string.Format("{0}({1}{2})", m.Method.Name, r, s2.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual List<Object> VisitExpressionList(ReadOnlyCollection<Expression> original)
|
||||
{
|
||||
var list = new List<Object>();
|
||||
for (int i = 0, n = original.Count; i < n; i++)
|
||||
{
|
||||
if (original[i].NodeType == ExpressionType.NewArrayInit ||
|
||||
original[i].NodeType == ExpressionType.NewArrayBounds)
|
||||
{
|
||||
|
||||
list.AddRange(VisitNewArrayFromExpressionList(original[i] as NewArrayExpression));
|
||||
}
|
||||
else
|
||||
list.Add(Visit(original[i]));
|
||||
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
protected virtual string VisitNewArray(NewArrayExpression na)
|
||||
{
|
||||
|
||||
List<Object> exprs = VisitExpressionList(na.Expressions);
|
||||
var r = new StringBuilder();
|
||||
foreach (Object e in exprs)
|
||||
{
|
||||
r.Append(r.Length > 0 ? "," + e : e);
|
||||
}
|
||||
|
||||
return r.ToString();
|
||||
}
|
||||
|
||||
protected virtual List<Object> VisitNewArrayFromExpressionList(NewArrayExpression na)
|
||||
{
|
||||
|
||||
List<Object> exprs = VisitExpressionList(na.Expressions);
|
||||
return exprs;
|
||||
}
|
||||
|
||||
|
||||
protected virtual string BindOperant(ExpressionType e)
|
||||
{
|
||||
|
||||
switch (e)
|
||||
{
|
||||
case ExpressionType.Equal:
|
||||
return "=";
|
||||
case ExpressionType.NotEqual:
|
||||
return "<>";
|
||||
case ExpressionType.GreaterThan:
|
||||
return ">";
|
||||
case ExpressionType.GreaterThanOrEqual:
|
||||
return ">=";
|
||||
case ExpressionType.LessThan:
|
||||
return "<";
|
||||
case ExpressionType.LessThanOrEqual:
|
||||
return "<=";
|
||||
case ExpressionType.AndAlso:
|
||||
return "AND";
|
||||
case ExpressionType.OrElse:
|
||||
return "OR";
|
||||
case ExpressionType.Add:
|
||||
return "+";
|
||||
case ExpressionType.Subtract:
|
||||
return "-";
|
||||
case ExpressionType.Multiply:
|
||||
return "*";
|
||||
case ExpressionType.Divide:
|
||||
return "/";
|
||||
case ExpressionType.Modulo:
|
||||
return "MOD";
|
||||
case ExpressionType.Coalesce:
|
||||
return "COALESCE";
|
||||
default:
|
||||
return e.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual string GetQuotedTableName(string tableName)
|
||||
{
|
||||
return string.Format("\"{0}\"", tableName);
|
||||
}
|
||||
|
||||
public virtual string GetQuotedColumnName(string columnName)
|
||||
{
|
||||
return string.Format("\"{0}\"", columnName);
|
||||
}
|
||||
|
||||
public virtual string GetQuotedName(string name)
|
||||
{
|
||||
return string.Format("\"{0}\"", name);
|
||||
}
|
||||
|
||||
private string GetQuotedTrueValue()
|
||||
{
|
||||
return GetQuotedValue(true, typeof(bool));
|
||||
}
|
||||
|
||||
private string GetQuotedFalseValue()
|
||||
{
|
||||
return GetQuotedValue(false, typeof(bool));
|
||||
}
|
||||
|
||||
public virtual string GetQuotedValue(object value, Type fieldType)
|
||||
{
|
||||
if (value == null) return "NULL";
|
||||
|
||||
if (!fieldType.UnderlyingSystemType.IsValueType && fieldType != typeof(string))
|
||||
{
|
||||
//if (TypeSerializer.CanCreateFromString(fieldType))
|
||||
//{
|
||||
// return "'" + EscapeParam(TypeSerializer.SerializeToString(value)) + "'";
|
||||
//}
|
||||
|
||||
throw new NotSupportedException(
|
||||
string.Format("Property of type: {0} is not supported", fieldType.FullName));
|
||||
}
|
||||
|
||||
if (fieldType == typeof(int))
|
||||
return ((int)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof(float))
|
||||
return ((float)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof(double))
|
||||
return ((double)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof(decimal))
|
||||
return ((decimal)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
return ShouldQuoteValue(fieldType)
|
||||
? "'" + EscapeParam(value) + "'"
|
||||
: value.ToString();
|
||||
}
|
||||
|
||||
public virtual string EscapeParam(object paramValue)
|
||||
{
|
||||
return paramValue.ToString().Replace("'", "''");
|
||||
}
|
||||
|
||||
public virtual bool ShouldQuoteValue(Type fieldType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual string GetFieldName(Database.PocoData pocoData, string name)
|
||||
{
|
||||
var column = pocoData.Columns.FirstOrDefault(x => x.Value.PropertyInfo.Name == name);
|
||||
return column.Value.ColumnName;
|
||||
}
|
||||
|
||||
protected virtual string GetFieldName(string name)
|
||||
{
|
||||
|
||||
if (useFieldName)
|
||||
{
|
||||
//FieldDefinition fd = modelDef.FieldDefinitions.FirstOrDefault(x => x.Name == name);
|
||||
//string fn = fd != default(FieldDefinition) ? fd.FieldName : name;
|
||||
//return OrmLiteConfig.DialectProvider.GetQuotedColumnName(fn);
|
||||
return "[" + name + "]";
|
||||
}
|
||||
else
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
protected string RemoveQuote(string exp)
|
||||
{
|
||||
|
||||
if (exp.StartsWith("'") && exp.EndsWith("'"))
|
||||
{
|
||||
exp = exp.Remove(0, 1);
|
||||
exp = exp.Remove(exp.Length - 1, 1);
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
|
||||
protected string RemoveQuoteFromAlias(string exp)
|
||||
{
|
||||
|
||||
if ((exp.StartsWith("\"") || exp.StartsWith("`") || exp.StartsWith("'"))
|
||||
&&
|
||||
(exp.EndsWith("\"") || exp.EndsWith("`") || exp.EndsWith("'")))
|
||||
{
|
||||
exp = exp.Remove(0, 1);
|
||||
exp = exp.Remove(exp.Length - 1, 1);
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
|
||||
private string GetTrueExpression()
|
||||
{
|
||||
object o = GetQuotedTrueValue();
|
||||
return string.Format("({0}={1})", o, o);
|
||||
}
|
||||
|
||||
private string GetFalseExpression()
|
||||
{
|
||||
|
||||
return string.Format("({0}={1})",
|
||||
GetQuotedTrueValue(),
|
||||
GetQuotedFalseValue());
|
||||
}
|
||||
|
||||
private bool IsTrueExpression(string exp)
|
||||
{
|
||||
return (exp == GetTrueExpression());
|
||||
}
|
||||
|
||||
private bool IsFalseExpression(string exp)
|
||||
{
|
||||
return (exp == GetFalseExpression());
|
||||
}
|
||||
|
||||
protected bool IsFieldName(string quotedExp)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/Umbraco.Core/Persistence/Querying/IQuery.cs
Normal file
10
src/Umbraco.Core/Persistence/Querying/IQuery.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
public interface IQuery<T>
|
||||
{
|
||||
IQuery<T> Where(Expression<Func<T, bool>> predicate);
|
||||
}
|
||||
}
|
||||
41
src/Umbraco.Core/Persistence/Querying/Query.cs
Normal file
41
src/Umbraco.Core/Persistence/Querying/Query.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
public class Query<T> : IQuery<T>
|
||||
{
|
||||
private readonly ExpressionHelper<T> _expresionist = new ExpressionHelper<T>();
|
||||
private readonly List<string> _wheres = new List<string>();
|
||||
|
||||
public Query()
|
||||
: base()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static IQuery<T> Builder
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Query<T>();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual IQuery<T> Where(Expression<Func<T, bool>> predicate)
|
||||
{
|
||||
if (predicate != null)
|
||||
{
|
||||
string whereExpression = _expresionist.Visit(predicate);
|
||||
_wheres.Add(whereExpression);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<string> WhereClauses()
|
||||
{
|
||||
return _wheres;
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/Umbraco.Core/Persistence/Querying/SqlTranslator.cs
Normal file
35
src/Umbraco.Core/Persistence/Querying/SqlTranslator.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
public class SqlTranslator<T>
|
||||
{
|
||||
private readonly Sql _sql;
|
||||
|
||||
public SqlTranslator(Sql sql, IQuery<T> query)
|
||||
{
|
||||
if (sql == null)
|
||||
throw new Exception("Sql cannot be null");
|
||||
|
||||
var query1 = query as Query<T>;
|
||||
if (query1 == null)
|
||||
throw new Exception("Query cannot be null");
|
||||
|
||||
_sql = sql;
|
||||
foreach (var clause in query1.WhereClauses())
|
||||
{
|
||||
_sql.Where(clause);
|
||||
}
|
||||
}
|
||||
|
||||
public Sql Translate()
|
||||
{
|
||||
return _sql;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return _sql.SQL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Relators
|
||||
{
|
||||
internal class TabPropertyTypeRelator
|
||||
{
|
||||
internal TabDto current;
|
||||
|
||||
internal TabDto Map(TabDto a, PropertyTypeDto p, DataTypeDto d)
|
||||
{
|
||||
// Terminating call. Since we can return null from this function
|
||||
// we need to be ready for PetaPoco to callback later with null
|
||||
// parameters
|
||||
if (a == null)
|
||||
return current;
|
||||
|
||||
//Set the PropertyTypeDto's DataTypeDto object
|
||||
if (p.DataTypeId == d.DataTypeId)
|
||||
p.DataTypeDto = d;
|
||||
|
||||
// Is this the same Tab as the current one we're processing
|
||||
if (current != null && current.Id == a.Id)
|
||||
{
|
||||
// Yes, just add this PropertyType to the current Tab's collection of PropertyTypes
|
||||
current.PropertyTypeDtos.Add(p);
|
||||
|
||||
// Return null to indicate we're not done with this Tab yet
|
||||
return null;
|
||||
}
|
||||
|
||||
// This is a different Tab to the current one, or this is the
|
||||
// first time through and we don't have a Tab yet
|
||||
|
||||
// Save the current Tab
|
||||
var prev = current;
|
||||
|
||||
// Setup the new current Tab
|
||||
current = a;
|
||||
current.PropertyTypeDtos = new List<PropertyTypeDto>();
|
||||
current.PropertyTypeDtos.Add(p);
|
||||
|
||||
// Return the now populated previous Tab (or null if first time through)
|
||||
return prev;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
293
src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
Normal file
293
src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
Normal file
@@ -0,0 +1,293 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.Caching;
|
||||
using Umbraco.Core.Persistence.Factories;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
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
|
||||
{
|
||||
private const string NodeObjectType = "C66BA18E-EAF3-4CFF-8A22-41B16D66A972";
|
||||
private readonly IContentTypeRepository _contentTypeRepository;
|
||||
|
||||
public ContentRepository(IUnitOfWork work, IContentTypeRepository contentTypeRepository)
|
||||
: base(work)
|
||||
{
|
||||
_contentTypeRepository = contentTypeRepository;
|
||||
}
|
||||
|
||||
internal ContentRepository(IUnitOfWork work, IContentTypeRepository contentTypeRepository, IRepositoryCacheProvider registry)
|
||||
: base(work, registry)
|
||||
{
|
||||
_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 });
|
||||
}
|
||||
|
||||
protected override IContent PerformGet(int id)
|
||||
{
|
||||
var contentSql = BaseSqlClause(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();
|
||||
|
||||
if (documentDto == null)
|
||||
return null;
|
||||
|
||||
var propertySql = new Sql();
|
||||
propertySql.Select("*");
|
||||
propertySql.From("cmsPropertyData");
|
||||
propertySql.InnerJoin("cmsPropertyType ON ([cmsPropertyData].[propertytypeid] = [cmsPropertyType].[id])");
|
||||
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 contentType = _contentTypeRepository.Get(documentDto.ContentVersionDto.ContentDto.ContentType);
|
||||
var content = ContentFactory.CreateContent(id, contentType, documentDto, propertyDataDtos);
|
||||
content.ResetDirtyProperties();
|
||||
return content;
|
||||
}
|
||||
|
||||
protected override IEnumerable<IContent> PerformGetAll(params int[] ids)
|
||||
{
|
||||
if (ids.Any())
|
||||
{
|
||||
foreach (var id in ids)
|
||||
{
|
||||
yield return Get(id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var nodeDtos = UnitOfWork.Storage.Fetch<NodeDto>("WHERE nodeObjectType = @NodeObjectType", new { NodeObjectType = NodeObjectType });
|
||||
foreach (var nodeDto in nodeDtos)
|
||||
{
|
||||
yield return Get(nodeDto.NodeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override IEnumerable<IContent> PerformGetByQuery(IQuery<IContent> query)
|
||||
{
|
||||
var sqlClause = BaseSqlClause(false);
|
||||
var translator = new SqlTranslator<IContent>(sqlClause, query);
|
||||
var sql = translator.Translate();
|
||||
|
||||
var documentDtos = UnitOfWork.Storage.Fetch<DocumentDto, ContentVersionDto, ContentDto, NodeDto>(sql);
|
||||
|
||||
foreach (var documentDto in documentDtos)
|
||||
{
|
||||
yield return Get(documentDto.NodeId);
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool PerformExists(int id)
|
||||
{
|
||||
return UnitOfWork.Storage.Exists<NodeDto>(id);
|
||||
}
|
||||
|
||||
protected override int PerformCount(IQuery<IContent> query)
|
||||
{
|
||||
var sqlClause = BaseSqlClause(true);
|
||||
var translator = new SqlTranslator<IContent>(sqlClause, query);
|
||||
var sql = translator.Translate();
|
||||
|
||||
return UnitOfWork.Storage.ExecuteScalar<int>(sql);
|
||||
}
|
||||
|
||||
public IEnumerable<IContent> GetAllVersions(int id)
|
||||
{
|
||||
var contentSql = BaseSqlClause(false);
|
||||
contentSql.Where("[cmsDocument].[nodeId] = @Id", new { Id = id });
|
||||
contentSql.OrderBy("[cmsContentVersion].[VersionDate] DESC");
|
||||
|
||||
var documentDtos = UnitOfWork.Storage.Fetch<DocumentDto, ContentVersionDto, ContentDto, NodeDto>(contentSql);
|
||||
foreach (var dto in documentDtos)
|
||||
{
|
||||
yield return GetByVersion(id, dto.ContentVersionDto.VersionId);
|
||||
}
|
||||
}
|
||||
|
||||
public IContent GetByVersion(int id, Guid versionId)
|
||||
{
|
||||
var contentSql = BaseSqlClause(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();
|
||||
|
||||
if (documentDto == null)
|
||||
return null;
|
||||
|
||||
var propertySql = new Sql();
|
||||
propertySql.Select("*");
|
||||
propertySql.From("cmsPropertyData");
|
||||
propertySql.InnerJoin("cmsPropertyType ON [cmsPropertyData].[propertytypeid] = [cmsPropertyType].[id]");
|
||||
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 contentType = _contentTypeRepository.Get(documentDto.ContentVersionDto.ContentDto.ContentType);
|
||||
var content = ContentFactory.CreateContent(id, contentType, documentDto, propertyDataDtos);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public interface IContentRepository : IRepository<IContent>
|
||||
{
|
||||
IEnumerable<IContent> GetAllVersions(int id);
|
||||
IContent GetByVersion(int id, Guid versionId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public interface IContentTypeRepository : IRepository<IContentType>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
67
src/Umbraco.Core/Persistence/Repositories/IRepository.cs
Normal file
67
src/Umbraco.Core/Persistence/Repositories/IRepository.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
/// <summary>
|
||||
/// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds or Updates an Entity
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
void AddOrUpdate(TEntity entity);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes an Entity
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
void Delete(TEntity entity);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an Entity by Id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
TEntity Get(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all entities of the spefified type
|
||||
/// </summary>
|
||||
/// <param name="ids"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<TEntity> GetAll(params int[] ids);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all entities of the spefified type and query
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<TEntity> GetByQuery(IQuery<TEntity> query);
|
||||
|
||||
/// <summary>
|
||||
/// Boolean indicating whether an Entity with the specified Id exists
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
bool Exists(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the count for the specified query
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <returns></returns>
|
||||
int Count(IQuery<TEntity> query);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the Unit Of Work for the Repository
|
||||
/// </summary>
|
||||
/// <param name="work"></param>
|
||||
void SetUnitOfWork(IUnitOfWork work);
|
||||
}
|
||||
}
|
||||
154
src/Umbraco.Core/Persistence/Repositories/Repository.cs
Normal file
154
src/Umbraco.Core/Persistence/Repositories/Repository.cs
Normal file
@@ -0,0 +1,154 @@
|
||||
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 _work;
|
||||
private readonly IRepositoryCacheProvider _cache;
|
||||
|
||||
protected Repository(IUnitOfWork work)
|
||||
: this(work, RuntimeCacheProvider.Current)
|
||||
{
|
||||
}
|
||||
|
||||
internal Repository(IUnitOfWork work, IRepositoryCacheProvider cache)
|
||||
{
|
||||
_work = work;
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
internal IUnitOfWork 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(IUnitOfWork work)
|
||||
{
|
||||
_work = work;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/Umbraco.Core/Persistence/UnitOfWork/IUnitOfWork.cs
Normal file
10
src/Umbraco.Core/Persistence/UnitOfWork/IUnitOfWork.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Persistence.UnitOfWork
|
||||
{
|
||||
public interface IUnitOfWork : IDisposable
|
||||
{
|
||||
void Commit();
|
||||
Database Storage { get; } //TODO consider replacing 'Database' with a datastorage adapter, so there is no direct dependency on PetaPoco
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Umbraco.Core.Persistence.UnitOfWork
|
||||
{
|
||||
public interface IUnitOfWorkProvider
|
||||
{
|
||||
IUnitOfWork GetUnitOfWork();
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Runtime.Caching" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
@@ -81,6 +82,23 @@
|
||||
<Compile Include="Models\Script.cs" />
|
||||
<Compile Include="Models\Stylesheet.cs" />
|
||||
<Compile Include="Models\Template.cs" />
|
||||
<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\Mappers\ModelDtoMapper.cs" />
|
||||
<Compile Include="Persistence\Querying\ExpressionHelper.cs" />
|
||||
<Compile Include="Persistence\Querying\IQuery.cs" />
|
||||
<Compile Include="Persistence\Querying\Query.cs" />
|
||||
<Compile Include="Persistence\Querying\SqlTranslator.cs" />
|
||||
<Compile Include="Persistence\Repositories\ContentRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\IContentRepository.cs" />
|
||||
<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\UnitOfWork\IUnitOfWork.cs" />
|
||||
<Compile Include="Persistence\UnitOfWork\IUnitOfWorkProvider.cs" />
|
||||
<Compile Include="PublishedContentExtensions.cs" />
|
||||
<Compile Include="Dictionary\ICultureDictionary.cs" />
|
||||
<Compile Include="Dynamics\ClassFactory.cs" />
|
||||
@@ -271,13 +289,7 @@
|
||||
<Name>umbraco.interfaces</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Persistence\Caching\" />
|
||||
<Folder Include="Persistence\Factories\" />
|
||||
<Folder Include="Persistence\Querying\" />
|
||||
<Folder Include="Persistence\Repositories\" />
|
||||
<Folder Include="Persistence\UnitOfWork\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
||||
Reference in New Issue
Block a user