Adding two missing properties to ContentTypeBase.

Creating mappers for the few types that supports "db queries" through the repository U4-978
This commit is contained in:
sitereactor
2012-10-23 11:29:16 -02:00
parent ee96ced595
commit a53dde8a20
19 changed files with 650 additions and 52 deletions

View File

@@ -82,6 +82,43 @@ namespace Umbraco.Core
});
}
public static MemberInfo FindProperty(LambdaExpression lambdaExpression)
{
Expression expressionToCheck = lambdaExpression;
bool done = false;
while (!done)
{
switch (expressionToCheck.NodeType)
{
case ExpressionType.Convert:
expressionToCheck = ((UnaryExpression)expressionToCheck).Operand;
break;
case ExpressionType.Lambda:
expressionToCheck = ((LambdaExpression)expressionToCheck).Body;
break;
case ExpressionType.MemberAccess:
var memberExpression = ((MemberExpression)expressionToCheck);
if (memberExpression.Expression.NodeType != ExpressionType.Parameter &&
memberExpression.Expression.NodeType != ExpressionType.Convert)
{
throw new ArgumentException(string.Format("Expression '{0}' must resolve to top-level member and not any child object's properties. Use a custom resolver on the child type or the AfterMap option instead.", lambdaExpression), "lambdaExpression");
}
MemberInfo member = memberExpression.Member;
return member;
default:
done = true;
break;
}
}
throw new Exception("Configuration for members is only supported for top-level individual members on a type.");
}
public static IDictionary<string, object> GetMethodParams<T1, T2>(Expression<Func<T1, T2>> fromExpression)
{
if (fromExpression == null) return null;

View File

@@ -22,6 +22,8 @@ namespace Umbraco.Core.Models
private string _icon;
private string _thumbnail;
private int _userId;
private bool _allowedAsRoot;
private bool _isContainer;
private bool _trashed;
private PropertyGroupCollection _propertyGroups;
private IEnumerable<ContentTypeSort> _allowedContentTypes;
@@ -43,6 +45,8 @@ namespace Umbraco.Core.Models
private static readonly PropertyInfo IconSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Icon);
private static readonly PropertyInfo ThumbnailSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Thumbnail);
private static readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.UserId);
private static readonly PropertyInfo AllowedAsRootSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.AllowedAsRoot);
private static readonly PropertyInfo IsContainerSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.IsContainer);
private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.Trashed);
private static readonly PropertyInfo AllowedContentTypesSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, IEnumerable<ContentTypeSort>>(x => x.AllowedContentTypes);
private static readonly PropertyInfo PropertyGroupCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, PropertyGroupCollection>(x => x.PropertyGroups);
@@ -193,6 +197,37 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Gets or Sets a boolean indicating whether this ContentType is allowed at the root
/// </summary>
[DataMember]
public virtual bool AllowedAsRoot
{
get { return _allowedAsRoot; }
set
{
_allowedAsRoot = value;
OnPropertyChanged(AllowedAsRootSelector);
}
}
/// <summary>
/// Gets or Sets a boolean indicating whether this ContentType is a Container
/// </summary>
/// <remarks>
/// ContentType Containers doesn't show children in the tree, but rather in grid-type view.
/// </remarks>
[DataMember]
public virtual bool IsContainer
{
get { return _isContainer; }
set
{
_isContainer = value;
OnPropertyChanged(IsContainerSelector);
}
}
/// <summary>
/// Boolean indicating whether this ContentType is Trashed or not.
/// If ContentType is Trashed it will be located in the Recyclebin.

View File

@@ -59,6 +59,19 @@ namespace Umbraco.Core.Models
/// </summary>
int UserId { get; set; }
/// <summary>
/// Gets or Sets a boolean indicating whether this ContentType is allowed at the root
/// </summary>
bool AllowedAsRoot { get; set; }
/// <summary>
/// Gets or Sets a boolean indicating whether this ContentType is a Container
/// </summary>
/// <remarks>
/// ContentType Containers doesn't show children in the tree, but rather in grid-type view.
/// </remarks>
bool IsContainer { get; set; }
/// <summary>
/// Gets or Sets a list of integer Ids of the ContentTypes allowed under the ContentType
/// </summary>

View File

@@ -38,6 +38,8 @@ namespace Umbraco.Core.Persistence.Factories
dto.ContentTypeDto.NodeDto.UserId.HasValue
? dto.ContentTypeDto.NodeDto.UserId.Value
: 0,
AllowedAsRoot = dto.ContentTypeDto.AllowAtRoot,
IsContainer = dto.ContentTypeDto.IsContainer,
Trashed = dto.ContentTypeDto.NodeDto.Trashed
};
return contentType;
@@ -62,6 +64,8 @@ namespace Umbraco.Core.Persistence.Factories
Icon = entity.Icon,
Thumbnail = entity.Thumbnail,
NodeId = entity.Id,
AllowAtRoot = entity.AllowedAsRoot,
IsContainer = entity.IsContainer,
NodeDto = BuildNodeDto(entity)
};
return contentTypeDto;

View File

@@ -38,6 +38,8 @@ namespace Umbraco.Core.Persistence.Factories
dto.NodeDto.UserId.HasValue
? dto.NodeDto.UserId.Value
: 0,
AllowedAsRoot = dto.AllowAtRoot,
IsContainer = dto.IsContainer,
Trashed = dto.NodeDto.Trashed
};
return contentType;
@@ -52,6 +54,8 @@ namespace Umbraco.Core.Persistence.Factories
Icon = entity.Icon,
Thumbnail = entity.Thumbnail,
NodeId = entity.Id,
AllowAtRoot = entity.AllowedAsRoot,
IsContainer = entity.IsContainer,
NodeDto = BuildNodeDto(entity)
};
return contentTypeDto;

View File

@@ -0,0 +1,38 @@
using System;
using System.Linq.Expressions;
using System.Reflection;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Mappers
{
internal abstract class BaseMapper
{
internal abstract void BuildMap();
internal abstract string Map(string propertyName);
internal abstract void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember);
internal DtoMapModel ResolveMapping<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
{
var source = ExpressionHelper.FindProperty(sourceMember);
var destination = ExpressionHelper.FindProperty(destinationMember) as PropertyInfo;
return new DtoMapModel(typeof(TDestination), destination, source.Name);
}
internal virtual string GetColumnName(Type dtoType, PropertyInfo dtoProperty)
{
var tableNameAttribute = dtoType.FirstAttribute<TableNameAttribute>();
string tableName = tableNameAttribute.Value;
var columnAttribute = dtoProperty.FirstAttribute<ColumnAttribute>();
string columnName = columnAttribute.Name;
string columnMap = string.Format("{0}.{1}",
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(tableName),
SyntaxConfig.SqlSyntaxProvider.GetQuotedColumnName(columnName));
return columnMap;
}
}
}

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Concurrent;
using System.Linq.Expressions;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Mappers
{
/// <summary>
/// Represents a <see cref="Content"/> to DTO mapper used to translate the properties of the public api
/// implementation to that of the database's DTO as sql: [tableName].[columnName].
/// </summary>
internal sealed class ContentMapper : BaseMapper
{
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
internal static ContentMapper Instance = new ContentMapper();
private ContentMapper()
{
BuildMap();
}
#region Overrides of BaseMapper
internal override void BuildMap()
{
if(PropertyInfoCache.IsEmpty)
{
CacheMap<Content, NodeDto>(src => src.Id, dto => dto.NodeId);
CacheMap<Content, NodeDto>(src => src.CreateDate, dto => dto.CreateDate);
CacheMap<Content, NodeDto>(src => src.Level, dto => dto.Level);
CacheMap<Content, NodeDto>(src => src.ParentId, dto => dto.ParentId);
CacheMap<Content, NodeDto>(src => src.Path, dto => dto.Path);
CacheMap<Content, NodeDto>(src => src.SortOrder, dto => dto.SortOrder);
CacheMap<Content, NodeDto>(src => src.Name, dto => dto.Text);
CacheMap<Content, NodeDto>(src => src.Trashed, dto => dto.Trashed);
CacheMap<Content, NodeDto>(src => src.Key, dto => dto.UniqueId);
CacheMap<Content, NodeDto>(src => src.UserId, dto => dto.UserId);
//CacheMap<Content, DocumentDto>(src => src.Name, dto => dto.Alias);
CacheMap<Content, DocumentDto>(src => src.ExpireDate, dto => dto.ExpiresDate);
CacheMap<Content, DocumentDto>(src => src.ReleaseDate, dto => dto.ReleaseDate);
CacheMap<Content, DocumentDto>(src => src.Published, dto => dto.Published);
CacheMap<Content, DocumentDto>(src => src.UpdateDate, dto => dto.UpdateDate);
//CacheMap<Content, DocumentDto>(src => src, dto => dto.Newest);
//CacheMap<Content, DocumentDto>(src => src.Template, dto => dto.TemplateId);
CacheMap<Content, DocumentDto>(src => src.Name, dto => dto.Text);
CacheMap<Content, DocumentDto>(src => src.Version, dto => dto.VersionId);
}
}
internal override string Map(string propertyName)
{
var dtoTypeProperty = PropertyInfoCache[propertyName];
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
}
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
{
var property = base.ResolveMapping(sourceMember, destinationMember);
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
}
#endregion
}
}

View File

@@ -0,0 +1,64 @@
using System;
using System.Collections.Concurrent;
using System.Linq.Expressions;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Mappers
{
/// <summary>
/// Represents a <see cref="ContentType"/> to DTO mapper used to translate the properties of the public api
/// implementation to that of the database's DTO as sql: [tableName].[columnName].
/// </summary>
internal sealed class ContentTypeMapper : BaseMapper
{
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
internal static ContentTypeMapper Instance = new ContentTypeMapper();
private ContentTypeMapper()
{
BuildMap();
}
#region Overrides of BaseMapper
internal override void BuildMap()
{
if (PropertyInfoCache.IsEmpty)
{
CacheMap<ContentType, NodeDto>(src => src.Id, dto => dto.NodeId);
CacheMap<ContentType, NodeDto>(src => src.CreateDate, dto => dto.CreateDate);
CacheMap<ContentType, NodeDto>(src => src.Level, dto => dto.Level);
CacheMap<ContentType, NodeDto>(src => src.ParentId, dto => dto.ParentId);
CacheMap<ContentType, NodeDto>(src => src.Path, dto => dto.Path);
CacheMap<ContentType, NodeDto>(src => src.SortOrder, dto => dto.SortOrder);
CacheMap<ContentType, NodeDto>(src => src.Name, dto => dto.Text);
CacheMap<ContentType, NodeDto>(src => src.Trashed, dto => dto.Trashed);
CacheMap<ContentType, NodeDto>(src => src.Key, dto => dto.UniqueId);
CacheMap<ContentType, NodeDto>(src => src.UserId, dto => dto.UserId);
CacheMap<ContentType, ContentTypeDto>(src => src.Alias, dto => dto.Alias);
CacheMap<ContentType, ContentTypeDto>(src => src.AllowedAsRoot, dto => dto.AllowAtRoot);
CacheMap<ContentType, ContentTypeDto>(src => src.Description, dto => dto.Description);
CacheMap<ContentType, ContentTypeDto>(src => src.Icon, dto => dto.Icon);
CacheMap<ContentType, ContentTypeDto>(src => src.IsContainer, dto => dto.IsContainer);
CacheMap<ContentType, ContentTypeDto>(src => src.Thumbnail, dto => dto.Thumbnail);
}
}
internal override string Map(string propertyName)
{
var dtoTypeProperty = PropertyInfoCache[propertyName];
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
}
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
{
var property = base.ResolveMapping(sourceMember, destinationMember);
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
}
#endregion
}
}

View File

@@ -0,0 +1,58 @@
using System;
using System.Collections.Concurrent;
using System.Linq.Expressions;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Mappers
{
/// <summary>
/// Represents a <see cref="DataTypeDefinition"/> to DTO mapper used to translate the properties of the public api
/// implementation to that of the database's DTO as sql: [tableName].[columnName].
/// </summary>
internal sealed class DataTypeDefinitionMapper : BaseMapper
{
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
internal static DataTypeDefinitionMapper Instance = new DataTypeDefinitionMapper();
private DataTypeDefinitionMapper()
{
BuildMap();
}
#region Overrides of BaseMapper
internal override void BuildMap()
{
CacheMap<DataTypeDefinition, NodeDto>(src => src.Id, dto => dto.NodeId);
CacheMap<DataTypeDefinition, NodeDto>(src => src.CreateDate, dto => dto.CreateDate);
CacheMap<DataTypeDefinition, NodeDto>(src => src.Level, dto => dto.Level);
CacheMap<DataTypeDefinition, NodeDto>(src => src.ParentId, dto => dto.ParentId);
CacheMap<DataTypeDefinition, NodeDto>(src => src.Path, dto => dto.Path);
CacheMap<DataTypeDefinition, NodeDto>(src => src.SortOrder, dto => dto.SortOrder);
CacheMap<DataTypeDefinition, NodeDto>(src => src.Name, dto => dto.Text);
CacheMap<DataTypeDefinition, NodeDto>(src => src.Trashed, dto => dto.Trashed);
CacheMap<DataTypeDefinition, NodeDto>(src => src.Key, dto => dto.UniqueId);
CacheMap<DataTypeDefinition, NodeDto>(src => src.UserId, dto => dto.UserId);
CacheMap<DataTypeDefinition, DataTypeDto>(src => src.ControlId, dto => dto.ControlId);
CacheMap<DataTypeDefinition, DataTypeDto>(src => src.DatabaseType, dto => dto.DbType);
}
internal override string Map(string propertyName)
{
var dtoTypeProperty = PropertyInfoCache[propertyName];
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
}
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
{
var property = base.ResolveMapping(sourceMember, destinationMember);
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
}
#endregion
}
}

View File

@@ -0,0 +1,52 @@
using System;
using System.Collections.Concurrent;
using System.Linq.Expressions;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Mappers
{
/// <summary>
/// Represents a <see cref="DictionaryItem"/> to DTO mapper used to translate the properties of the public api
/// implementation to that of the database's DTO as sql: [tableName].[columnName].
/// </summary>
internal sealed class DictionaryMapper : BaseMapper
{
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
internal static DictionaryMapper Instance = new DictionaryMapper();
private DictionaryMapper()
{
BuildMap();
}
#region Overrides of BaseMapper
internal override void BuildMap()
{
CacheMap<DictionaryItem, DictionaryDto>(src => src.Id, dto => dto.Id);
CacheMap<DictionaryItem, DictionaryDto>(src => src.ItemKey, dto => dto.Key);
CacheMap<DictionaryItem, DictionaryDto>(src => src.ParentId, dto => dto.Parent);
CacheMap<DictionaryTranslation, LanguageTextDto>(src => src.Key, dto => dto.UniqueId);
CacheMap<DictionaryTranslation, LanguageTextDto>(src => src.Language.Id, dto => dto.LanguageId);
CacheMap<DictionaryTranslation, LanguageTextDto>(src => src.Value, dto => dto.Value);
}
internal override string Map(string propertyName)
{
var dtoTypeProperty = PropertyInfoCache[propertyName];
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
}
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
{
var property = base.ResolveMapping(sourceMember, destinationMember);
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
}
#endregion
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Reflection;
namespace Umbraco.Core.Persistence.Mappers
{
internal class DtoMapModel
{
public DtoMapModel(Type type, PropertyInfo propertyInfo, string sourcePropertyName)
{
Type = type;
PropertyInfo = propertyInfo;
SourcePropertyName = sourcePropertyName;
}
public string SourcePropertyName { get; set; }
public Type Type { get; set; }
public PropertyInfo PropertyInfo { get; set; }
}
}

View File

@@ -0,0 +1,48 @@
using System;
using System.Collections.Concurrent;
using System.Linq.Expressions;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Mappers
{
/// <summary>
/// Represents a <see cref="Language"/> to DTO mapper used to translate the properties of the public api
/// implementation to that of the database's DTO as sql: [tableName].[columnName].
/// </summary>
internal sealed class LanguageMapper : BaseMapper
{
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
internal static LanguageMapper Instance = new LanguageMapper();
private LanguageMapper()
{
BuildMap();
}
#region Overrides of BaseMapper
internal override void BuildMap()
{
CacheMap<Language, LanguageDto>(src => src.Id, dto => dto.Id);
CacheMap<Language, LanguageDto>(src => src.IsoCode, dto => dto.IsoCode);
CacheMap<Language, LanguageDto>(src => src.CultureName, dto => dto.CultureName);
}
internal override string Map(string propertyName)
{
var dtoTypeProperty = PropertyInfoCache[propertyName];
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
}
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
{
var property = base.ResolveMapping(sourceMember, destinationMember);
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
}
#endregion
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Concurrent;
using System.Linq.Expressions;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Mappers
{
/// <summary>
/// Represents a <see cref="Models.Media"/> to DTO mapper used to translate the properties of the public api
/// implementation to that of the database's DTO as sql: [tableName].[columnName].
/// </summary>
internal sealed class MediaMapper : BaseMapper
{
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
internal static MediaMapper Instance = new MediaMapper();
private MediaMapper()
{
BuildMap();
}
#region Overrides of BaseMapper
internal override void BuildMap()
{
if (PropertyInfoCache.IsEmpty)
{
CacheMap<Models.Media, NodeDto>(src => src.Id, dto => dto.NodeId);
CacheMap<Models.Media, NodeDto>(src => src.CreateDate, dto => dto.CreateDate);
CacheMap<Models.Media, NodeDto>(src => src.Level, dto => dto.Level);
CacheMap<Models.Media, NodeDto>(src => src.ParentId, dto => dto.ParentId);
CacheMap<Models.Media, NodeDto>(src => src.Path, dto => dto.Path);
CacheMap<Models.Media, NodeDto>(src => src.SortOrder, dto => dto.SortOrder);
CacheMap<Models.Media, NodeDto>(src => src.Name, dto => dto.Text);
CacheMap<Models.Media, NodeDto>(src => src.Trashed, dto => dto.Trashed);
CacheMap<Models.Media, NodeDto>(src => src.Key, dto => dto.UniqueId);
CacheMap<Models.Media, NodeDto>(src => src.UserId, dto => dto.UserId);
}
}
internal override string Map(string propertyName)
{
var dtoTypeProperty = PropertyInfoCache[propertyName];
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
}
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
{
var property = base.ResolveMapping(sourceMember, destinationMember);
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
}
#endregion
}
}

View File

@@ -4,6 +4,9 @@ using Umbraco.Core.Models;
namespace Umbraco.Core.Persistence.Mappers
{
/// <summary>
/// Public api models to DTO mapper used by PetaPoco to map Properties to Columns
/// </summary>
internal class ModelDtoMapper : IMapper
{
public void GetTableInfo(Type t, TableInfo ti)
@@ -13,61 +16,44 @@ namespace Umbraco.Core.Persistence.Mappers
{
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 "CreateDate":
columnName = "[umbracoNode].[createDate]";
return true;
case "Name":
columnName = "[umbracoNode].[text]";
return true;
}
columnName = ContentMapper.Instance.Map(pi.Name);
return true;
}
if (pi.DeclaringType == typeof(ContentType) || pi.DeclaringType == typeof(IContentType))
if (pi.DeclaringType == typeof(Models.Media) || pi.DeclaringType == typeof(IMedia))
{
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;
}
columnName = MediaMapper.Instance.Map(pi.Name);
return true;
}
if (pi.DeclaringType == typeof(ContentType) || pi.DeclaringType == typeof(IContentType) || pi.DeclaringType == typeof(IMediaType))
{
columnName = ContentTypeMapper.Instance.Map(pi.Name);
}
if (pi.DeclaringType == typeof(DataTypeDefinition))
{
columnName = DataTypeDefinitionMapper.Instance.Map(pi.Name);
}
if (pi.DeclaringType == typeof(DictionaryItem))
{
columnName = DictionaryMapper.Instance.Map(pi.Name);
}
if (pi.DeclaringType == typeof(Language))
{
columnName = LanguageMapper.Instance.Map(pi.Name);
}
if (pi.DeclaringType == typeof(Relation))
{
columnName = RelationMapper.Instance.Map(pi.Name);
}
if (pi.DeclaringType == typeof(RelationType))
{
columnName = RelationTypeMapper.Instance.Map(pi.Name);
}
return true;

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Concurrent;
using System.Linq.Expressions;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Mappers
{
/// <summary>
/// Represents a <see cref="Relation"/> to DTO mapper used to translate the properties of the public api
/// implementation to that of the database's DTO as sql: [tableName].[columnName].
/// </summary>
internal sealed class RelationMapper : BaseMapper
{
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
internal static RelationMapper Instance = new RelationMapper();
private RelationMapper()
{
BuildMap();
}
#region Overrides of BaseMapper
internal override void BuildMap()
{
CacheMap<Relation, RelationDto>(src => src.Id, dto => dto.Id);
CacheMap<Relation, RelationDto>(src => src.ChildId, dto => dto.ChildId);
CacheMap<Relation, RelationDto>(src => src.Comment, dto => dto.Comment);
CacheMap<Relation, RelationDto>(src => src.CreateDate, dto => dto.Datetime);
CacheMap<Relation, RelationDto>(src => src.ParentId, dto => dto.ParentId);
CacheMap<Relation, RelationDto>(src => src.RelationType.Id, dto => dto.RelationType);
}
internal override string Map(string propertyName)
{
var dtoTypeProperty = PropertyInfoCache[propertyName];
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
}
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
{
var property = base.ResolveMapping(sourceMember, destinationMember);
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
}
#endregion
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Concurrent;
using System.Linq.Expressions;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Mappers
{
/// <summary>
/// Represents a <see cref="RelationType"/> to DTO mapper used to translate the properties of the public api
/// implementation to that of the database's DTO as sql: [tableName].[columnName].
/// </summary>
internal sealed class RelationTypeMapper : BaseMapper
{
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
internal static RelationTypeMapper Instance = new RelationTypeMapper();
private RelationTypeMapper()
{
BuildMap();
}
#region Overrides of BaseMapper
internal override void BuildMap()
{
CacheMap<RelationType, RelationTypeDto>(src => src.Id, dto => dto.Id);
CacheMap<RelationType, RelationTypeDto>(src => src.Alias, dto => dto.Alias);
CacheMap<RelationType, RelationTypeDto>(src => src.ChildObjectType, dto => dto.ChildObjectType);
CacheMap<RelationType, RelationTypeDto>(src => src.IsBidirectional, dto => dto.Dual);
CacheMap<RelationType, RelationTypeDto>(src => src.Name, dto => dto.Name);
CacheMap<RelationType, RelationTypeDto>(src => src.ParentObjectType, dto => dto.ParentObjectType);
}
internal override string Map(string propertyName)
{
var dtoTypeProperty = PropertyInfoCache[propertyName];
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
}
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
{
var property = base.ResolveMapping(sourceMember, destinationMember);
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
}
#endregion
}
}

View File

@@ -79,6 +79,7 @@ namespace Umbraco.Core.Persistence.Repositories
var translator = new SqlTranslator<IContent>(sqlClause, query);
var sql = translator.Translate();
//NOTE: This doesn't allow properties to be part of the query
var dtos = Database.Fetch<DocumentDto, ContentVersionDto, ContentDto, NodeDto>(sql);
foreach (var dto in dtos)

View File

@@ -10,6 +10,9 @@ using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Persistence.Repositories
{
/// <summary>
/// Represents a repository for doing CRUD operations for <see cref="Language"/>
/// </summary>
internal class LanguageRepository : PetaPocoRepositoryBase<int, Language>, ILanguageRepository
{
public LanguageRepository(IUnitOfWork work) : base(work)

View File

@@ -130,7 +130,17 @@
<Compile Include="Persistence\Factories\PropertyGroupFactory.cs" />
<Compile Include="Persistence\Factories\RelationFactory.cs" />
<Compile Include="Persistence\Factories\RelationTypeFactory.cs" />
<Compile Include="Persistence\Mappers\BaseMapper.cs" />
<Compile Include="Persistence\Mappers\ContentMapper.cs" />
<Compile Include="Persistence\Mappers\ContentTypeMapper.cs" />
<Compile Include="Persistence\Mappers\DataTypeDefinitionMapper.cs" />
<Compile Include="Persistence\Mappers\DictionaryMapper.cs" />
<Compile Include="Persistence\Mappers\DtoMapModel.cs" />
<Compile Include="Persistence\Mappers\LanguageMapper.cs" />
<Compile Include="Persistence\Mappers\MediaMapper.cs" />
<Compile Include="Persistence\Mappers\ModelDtoMapper.cs" />
<Compile Include="Persistence\Mappers\RelationMapper.cs" />
<Compile Include="Persistence\Mappers\RelationTypeMapper.cs" />
<Compile Include="Persistence\Migrations\Initial\BaseDataCreation.cs" />
<Compile Include="Persistence\Migrations\Initial\DatabaseCreation.cs" />
<Compile Include="Persistence\PetaPocoExtensions.cs" />