Implementing read-only DTOs for improved reading of Members from db.

Started implementation of Member, MemberType and MemberGroup repositories.
This commit is contained in:
Morten Christensen
2013-08-26 16:59:41 +02:00
parent f1818aae1b
commit 37d190c97d
9 changed files with 350 additions and 0 deletions

View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Persistence;
namespace Umbraco.Core.Models.Rdbms
{
[TableName("umbracoNode")]
[PrimaryKey("id")]
[ExplicitColumns]
public class MemberReadOnlyDto
{
/* from umbracoNode */
[Column("id")]
public int NodeId { get; set; }
[Column("trashed")]
public bool Trashed { get; set; }
[Column("parentID")]
public int ParentId { get; set; }
[Column("nodeUser")]
public int? UserId { get; set; }
[Column("level")]
public short Level { get; set; }
[Column("path")]
public string Path { get; set; }
[Column("sortOrder")]
public int SortOrder { get; set; }
[Column("uniqueID")]
public Guid? UniqueId { get; set; }
[Column("text")]
public string Text { get; set; }
[Column("nodeObjectType")]
public Guid? NodeObjectType { get; set; }
[Column("createDate")]
public DateTime CreateDate { get; set; }
/* from cmsContentType joined with cmsContent */
[Column("ContentTypeAlias")]
public string ContentTypeAlias { get; set; }
/* cmsContentVersion */
[Column("VersionId")]
public Guid VersionId { get; set; }
[Column("VersionDate")]
public DateTime UpdateDate { get; set; }
[Column("LanguageLocale")]
public string Language { get; set; }
/* cmsMember */
[Column("Email")]
public string Email { get; set; }
[Column("LoginName")]
public string LoginName { get; set; }
[Column("Password")]
public string Password { get; set; }
/* Properties */
[ResultColumn]
public List<PropertyDataReadOnlyDto> Properties { get; set; }
}
}

View File

@@ -0,0 +1,65 @@
using System;
using Umbraco.Core.Persistence;
namespace Umbraco.Core.Models.Rdbms
{
[TableName("cmsPropertyData")]
[PrimaryKey("id")]
[ExplicitColumns]
public class PropertyDataReadOnlyDto
{
/* cmsPropertyData */
[Column("id")]
public int Id { get; set; }
[Column("contentNodeId")]
public int NodeId { get; set; }
[Column("VersionId")]
public Guid? VersionId { get; set; }
[Column("propertytypeid")]
public int PropertyTypeId { get; set; }
[Column("dataInt")]
public int? Integer { get; set; }
[Column("dataDate")]
public DateTime? Date { get; set; }
[Column("dataNvarchar")]
public string VarChar { get; set; }
[Column("dataNtext")]
public string Text { get; set; }
/* cmsPropertyType */
[Column("dataTypeId")]
public int DataTypeId { get; set; }
[Column("propertyTypeGroupId")]
public int? PropertyTypeGroupId { get; set; }
[Column("Alias")]
public string Alias { get; set; }
[Column("Name")]
public string Name { get; set; }
[Column("helpText")]
public string HelpText { get; set; }
[Column("mandatory")]
public bool Mandatory { get; set; }
[Column("validationRegExp")]
public string ValidationRegExp { get; set; }
[Column("Description")]
public string Description { get; set; }
/* cmsDataType */
[Column("controlId")]
public Guid ControlId { get; set; }
}
}

View File

@@ -0,0 +1,43 @@
using System.Collections.Generic;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Relators
{
internal class PropertyDataRelator
{
internal MemberReadOnlyDto Current;
internal MemberReadOnlyDto Map(MemberReadOnlyDto a, PropertyDataReadOnlyDto p)
{
// 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;
// Is this the same MemberReadOnlyDto as the current one we're processing
if (Current != null && Current.UniqueId == a.UniqueId)
{
// Yes, just add this PropertyDataReadOnlyDto to the current MemberReadOnlyDto's collection
Current.Properties.Add(p);
// Return null to indicate we're not done with this MemberReadOnlyDto yet
return null;
}
// This is a different MemberReadOnlyDto to the current one, or this is the
// first time through and we don't have a Tab yet
// Save the current MemberReadOnlyDto
var prev = Current;
// Setup the new current MemberReadOnlyDto
Current = a;
Current.Properties = new List<PropertyDataReadOnlyDto>();
Current.Properties.Add(p);
// Return the now populated previous MemberReadOnlyDto (or null if first time through)
return prev;
}
}
}

View File

@@ -0,0 +1,9 @@
using Umbraco.Core.Models.Membership;
namespace Umbraco.Core.Persistence.Repositories
{
internal interface IMemberRepository : IRepositoryVersionable<int, IMembershipUser>
{
}
}

View File

@@ -0,0 +1,7 @@
namespace Umbraco.Core.Persistence.Repositories
{
public class MemberGroupRepository
{
}
}

View File

@@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.Caching;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.Relators;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Persistence.Repositories
{
internal class MemberRepository : VersionableRepositoryBase<int, IMembershipUser>, IMemberRepository
{
public MemberRepository(IDatabaseUnitOfWork work) : base(work)
{
}
public MemberRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) : base(work, cache)
{
}
/* The following methods might be relevant for this specific repository (in an optimized form)
* GetById - get a member by its integer Id
* GetByKey - get a member by its unique guid Id (which should correspond to a membership provider user's id)
* GetByPropertyValue - get members with a certain property value (supply both property alias and value?)
* GetByMemberTypeAlias - get all members of a certain type
* GetByMemberGroup - get all members in a specific group
* GetAllMembers
*/
#region Overrides of RepositoryBase<int, IMembershipUser>
protected override IMembershipUser PerformGet(int id)
{
var sql = GetBaseQuery(false);
sql.Where(GetBaseWhereClause(), new { Id = id });
sql.OrderByDescending<ContentVersionDto>(x => x.VersionDate);
var dto =
Database.Fetch<MemberReadOnlyDto, PropertyDataReadOnlyDto, MemberReadOnlyDto>(
new PropertyDataRelator().Map, sql);
if (dto == null || dto.Any() == false)
return null;
return new Member();
}
protected override IEnumerable<IMembershipUser> PerformGetAll(params int[] ids)
{
throw new NotImplementedException();
}
protected override IEnumerable<IMembershipUser> PerformGetByQuery(IQuery<IMembershipUser> query)
{
throw new NotImplementedException();
}
#endregion
#region Overrides of PetaPocoRepositoryBase<int,IMembershipUser>
protected override Sql GetBaseQuery(bool isCount)
{
//TODO Count
var sql = new Sql();
sql.Select("umbracoNode.*", "cmsContentType.alias AS ContentTypeAlias", "cmsContentVersion.VersionId",
"cmsContentVersion.VersionDate", "cmsContentVersion.LanguageLocale", "cmsMember.Email",
"cmsMember.LoginName", "cmsMember.Password", "cmsPropertyData.id", "cmsPropertyData.dataDate",
"cmsPropertyData.dataInt", "cmsPropertyData.dataNtext", "cmsPropertyData.dataNvarchar",
"cmsPropertyData.propertytypeid", "cmsPropertyType.Alias", "cmsPropertyType.Description",
"cmsPropertyType.Name", "cmsPropertyType.mandatory", "cmsPropertyType.validationRegExp",
"cmsPropertyType.helpText", "cmsPropertyType.propertyTypeGroupId", "cmsPropertyType.dataTypeId",
"cmsDataType.controlId")
.From<NodeDto>()
.InnerJoin<ContentDto>().On<ContentDto, NodeDto>(left => left.NodeId, right => right.NodeId)
.InnerJoin<ContentTypeDto>().On<ContentTypeDto, ContentDto>(left => left.NodeId, right => right.ContentTypeId)
.InnerJoin<ContentVersionDto>().On<ContentVersionDto, NodeDto>(left => left.NodeId, right => right.NodeId)
.InnerJoin<MemberDto>().On<MemberDto, ContentDto>(left => left.NodeId, right => right.NodeId)
.LeftJoin<PropertyDataDto>().On<PropertyDataDto, ContentVersionDto>(left => left.VersionId, right => right.VersionId)
.LeftJoin<PropertyTypeDto>().On<PropertyTypeDto, PropertyDataDto>(left => left.Id, right => right.PropertyTypeId)
.LeftJoin<DataTypeDto>().On<DataTypeDto, PropertyTypeDto>(left => left.DataTypeId, right => right.DataTypeId)
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId);
return sql;
}
protected override string GetBaseWhereClause()
{
return "umbracoNode.id = @Id";
}
protected override IEnumerable<string> GetDeleteClauses()
{
throw new NotImplementedException();
}
protected override Guid NodeObjectTypeId
{
get { return new Guid(Constants.ObjectTypes.Member); }
}
#endregion
#region Unit of Work Implementation
protected override void PersistNewItem(IMembershipUser entity)
{
throw new NotImplementedException();
}
protected override void PersistUpdatedItem(IMembershipUser entity)
{
throw new NotImplementedException();
}
#endregion
#region Overrides of VersionableRepositoryBase<IMembershipUser>
public override IMembershipUser GetByVersion(Guid versionId)
{
throw new NotImplementedException();
}
protected override void PerformDeleteVersion(int id, Guid versionId)
{
throw new NotImplementedException();
}
#endregion
}
}

View File

@@ -0,0 +1,7 @@
namespace Umbraco.Core.Persistence.Repositories
{
public class MemberTypeRepository
{
}
}

View File

@@ -115,6 +115,11 @@ namespace Umbraco.Core.Persistence
CreateUserTypeRepository(uow));
}
internal virtual IMemberRepository CreateMemberRepository(IDatabaseUnitOfWork uow)
{
return new MemberRepository(uow, RuntimeCacheProvider.Current);
}
internal virtual IEntityRepository CreateEntityRepository(IDatabaseUnitOfWork uow)
{
return new EntityRepository(uow);

View File

@@ -201,6 +201,8 @@
<Compile Include="Models\IFile.cs" />
<Compile Include="Models\ILanguage.cs" />
<Compile Include="Models\Membership\UmbracoMembershipUser.cs" />
<Compile Include="Models\Rdbms\MemberReadOnlyDto.cs" />
<Compile Include="Models\Rdbms\PropertyDataReadOnlyDto.cs" />
<Compile Include="Models\ServerRegistration.cs" />
<Compile Include="Models\ITemplate.cs" />
<Compile Include="Models\Language.cs" />
@@ -468,6 +470,7 @@
<Compile Include="Persistence\Querying\Query.cs" />
<Compile Include="Persistence\Querying\SqlTranslator.cs" />
<Compile Include="Persistence\Relators\DictionaryLanguageTextRelator.cs" />
<Compile Include="Persistence\Relators\PropertyDataRelator.cs" />
<Compile Include="Persistence\Relators\UserSectionRelator.cs" />
<Compile Include="Persistence\Repositories\ContentRepository.cs" />
<Compile Include="Persistence\Repositories\ContentTypeBaseRepository.cs" />
@@ -484,6 +487,7 @@
<Compile Include="Persistence\Repositories\Interfaces\ILanguageRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IMediaRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IMediaTypeRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IMemberRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IRelationRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IRelationTypeRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IRepositoryQueryable.cs" />
@@ -498,6 +502,9 @@
<Compile Include="Persistence\Repositories\LanguageRepository.cs" />
<Compile Include="Persistence\Repositories\MediaRepository.cs" />
<Compile Include="Persistence\Repositories\MediaTypeRepository.cs" />
<Compile Include="Persistence\Repositories\MemberGroupRepository.cs" />
<Compile Include="Persistence\Repositories\MemberRepository.cs" />
<Compile Include="Persistence\Repositories\MemberTypeRepository.cs" />
<Compile Include="Persistence\Repositories\PermissionRepository.cs" />
<Compile Include="Persistence\Repositories\PetaPocoRepositoryBase.cs" />
<Compile Include="Persistence\Repositories\RecycleBinRepository.cs" />