Updated the member service/repo to have paged queries and results which use db paging for maximum efficiency (of course only works for things like email, username but those are 2 specific things that are needed by the membership provider)

This commit is contained in:
Shannon
2013-12-20 18:11:12 +11:00
parent a4dde1948f
commit 7a8b3dc9bc
7 changed files with 111 additions and 31 deletions

View File

@@ -1,5 +1,8 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.Querying;
namespace Umbraco.Core.Persistence.Repositories
@@ -27,5 +30,16 @@ namespace Umbraco.Core.Persistence.Repositories
/// <returns></returns>
int GetCountByQuery(IQuery<IMember> query);
/// <summary>
/// Gets paged member results
/// </summary>
/// <param name="query"></param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalRecords"></param>
/// <param name="orderBy"></param>
/// <returns></returns>
IEnumerable<IMember> GetPagedResultsByQuery(IQuery<IMember> query, int pageIndex, int pageSize, out int totalRecords, Expression<Func<IMember, string>> orderBy);
}
}

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Models.EntityBase;
@@ -9,6 +10,7 @@ using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.Caching;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.Relators;
using Umbraco.Core.Persistence.UnitOfWork;
@@ -460,6 +462,51 @@ namespace Umbraco.Core.Persistence.Repositories
return Database.ExecuteScalar<int>(sql);
}
/// <summary>
/// Gets paged member results
/// </summary>
/// <param name="query"></param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalRecords"></param>
/// <param name="orderBy"></param>
/// <returns></returns>
/// <remarks>
/// The query supplied will ONLY work with data specifically on the cmsMember table because we are using PetaPoco paging (SQL paging)
/// </remarks>
public IEnumerable<IMember> GetPagedResultsByQuery(IQuery<IMember> query, int pageIndex, int pageSize, out int totalRecords, Expression<Func<IMember, string>> orderBy)
{
if (orderBy == null) throw new ArgumentNullException("orderBy");
var sql = new Sql();
sql.Select("*").From<MemberDto>();
var translator = new SqlTranslator<IMember>(sql, query);
var resultQuery = translator.Translate();
//get the referenced column name
var expressionMember = ExpressionHelper.GetMemberInfo(orderBy);
//now find the mapped column name
var mapper = MappingResolver.Current.ResolveMapperByType(typeof(IMember));
var mappedField = mapper.Map(expressionMember.Name);
if (mappedField.IsNullOrWhiteSpace())
{
throw new ArgumentException("Could not find a mapping for the column specified in the orderBy clause");
}
//need to ensure the order by is in brackets, see: https://github.com/toptensoftware/PetaPoco/issues/177
resultQuery.OrderBy(string.Format("({0})", mappedField));
var pagedResult = Database.Page<MemberDto>(pageIndex + 1, pageSize, resultQuery);
totalRecords = Convert.ToInt32(pagedResult.TotalItems);
//now that we have the member dto's we need to construct true members from the list.
var result = GetAll(pagedResult.Items.Select(x => x.NodeId).ToArray());
//now we need to ensure this result is also ordered by the same order by clause
return result.OrderBy(orderBy.Compile());
}
private IMember BuildFromDto(List<MemberReadOnlyDto> dtos)
{
if (dtos == null || dtos.Any() == false)

View File

@@ -46,9 +46,9 @@ namespace Umbraco.Core.Services
void Save(IEnumerable<IMember> members, bool raiseEvents = true);
IEnumerable<IMember> FindMembersByEmail(string emailStringToMatch, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith);
IEnumerable<IMember> FindMembersByEmail(string emailStringToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith);
IEnumerable<IMember> FindMembersByUsername(string login, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith);
IEnumerable<IMember> FindMembersByUsername(string login, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith);
/// <summary>
/// Gets the total number of members based on the count type

View File

@@ -184,9 +184,12 @@ namespace Umbraco.Core.Services
/// Does a search for members that contain the specified string in their email address
/// </summary>
/// <param name="emailStringToMatch"></param>
/// <param name="totalRecords"></param>
/// <param name="matchType"></param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
public IEnumerable<IMember> FindMembersByEmail(string emailStringToMatch, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
public IEnumerable<IMember> FindMembersByEmail(string emailStringToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberRepository(uow))
@@ -214,11 +217,13 @@ namespace Umbraco.Core.Services
throw new ArgumentOutOfRangeException("matchType");
}
return repository.GetByQuery(query);
return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, dto => dto.Email);
//return repository.GetByQuery(query);
}
}
public IEnumerable<IMember> FindMembersByUsername(string login, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
public IEnumerable<IMember> FindMembersByUsername(string login, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberRepository(uow))
@@ -246,7 +251,9 @@ namespace Umbraco.Core.Services
throw new ArgumentOutOfRangeException("matchType");
}
return repository.GetByQuery(query);
return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, dto => dto.Username);
//return repository.GetByQuery(query);
}
}

View File

@@ -123,7 +123,8 @@ namespace Umbraco.Tests.Services
var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello","hello");
ServiceContext.MemberService.Save(customMember);
var found = ServiceContext.MemberService.FindMembersByEmail("tes", StringPropertyMatchType.StartsWith);
int totalRecs;
var found = ServiceContext.MemberService.FindMembersByEmail("tes", 0, 100, out totalRecs, StringPropertyMatchType.StartsWith);
Assert.AreEqual(10, found.Count());
}
@@ -139,7 +140,8 @@ namespace Umbraco.Tests.Services
var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello");
ServiceContext.MemberService.Save(customMember);
var found = ServiceContext.MemberService.FindMembersByEmail("test.com", StringPropertyMatchType.EndsWith);
int totalRecs;
var found = ServiceContext.MemberService.FindMembersByEmail("test.com", 0, 100, out totalRecs, StringPropertyMatchType.EndsWith);
Assert.AreEqual(11, found.Count());
}
@@ -155,7 +157,8 @@ namespace Umbraco.Tests.Services
var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello");
ServiceContext.MemberService.Save(customMember);
var found = ServiceContext.MemberService.FindMembersByEmail("test", StringPropertyMatchType.Contains);
int totalRecs;
var found = ServiceContext.MemberService.FindMembersByEmail("test", 0, 100, out totalRecs, StringPropertyMatchType.Contains);
Assert.AreEqual(11, found.Count());
}
@@ -171,7 +174,8 @@ namespace Umbraco.Tests.Services
var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello");
ServiceContext.MemberService.Save(customMember);
var found = ServiceContext.MemberService.FindMembersByEmail("hello@test.com", StringPropertyMatchType.Exact);
int totalRecs;
var found = ServiceContext.MemberService.FindMembersByEmail("hello@test.com", 0, 100, out totalRecs, StringPropertyMatchType.Exact);
Assert.AreEqual(1, found.Count());
}
@@ -187,7 +191,8 @@ namespace Umbraco.Tests.Services
var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello");
ServiceContext.MemberService.Save(customMember);
var found = ServiceContext.MemberService.FindMembersByUsername("tes", StringPropertyMatchType.StartsWith);
int totalRecs;
var found = ServiceContext.MemberService.FindMembersByUsername("tes", 0, 100, out totalRecs, StringPropertyMatchType.StartsWith);
Assert.AreEqual(10, found.Count());
}
@@ -203,7 +208,8 @@ namespace Umbraco.Tests.Services
var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello");
ServiceContext.MemberService.Save(customMember);
var found = ServiceContext.MemberService.FindMembersByUsername("llo", StringPropertyMatchType.EndsWith);
int totalRecs;
var found = ServiceContext.MemberService.FindMembersByUsername("llo", 0, 100, out totalRecs, StringPropertyMatchType.EndsWith);
Assert.AreEqual(1, found.Count());
}
@@ -219,7 +225,8 @@ namespace Umbraco.Tests.Services
var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hellotest");
ServiceContext.MemberService.Save(customMember);
var found = ServiceContext.MemberService.FindMembersByUsername("test", StringPropertyMatchType.Contains);
int totalRecs;
var found = ServiceContext.MemberService.FindMembersByUsername("test", 0, 100, out totalRecs, StringPropertyMatchType.Contains);
Assert.AreEqual(11, found.Count());
}
@@ -235,7 +242,8 @@ namespace Umbraco.Tests.Services
var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello");
ServiceContext.MemberService.Save(customMember);
var found = ServiceContext.MemberService.FindMembersByUsername("hello", StringPropertyMatchType.Exact);
int totalRecs;
var found = ServiceContext.MemberService.FindMembersByUsername("hello", 0, 100, out totalRecs, StringPropertyMatchType.Exact);
Assert.AreEqual(1, found.Count());
}

View File

@@ -203,12 +203,13 @@ namespace Umbraco.Web.Security.Providers
/// </returns>
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
{
var byEmail = MemberService.FindMembersByEmail(emailToMatch, StringPropertyMatchType.Wildcard).ToArray();
totalRecords = byEmail.Length;
var pagedResult = new PagedResult<IMember>(totalRecords, pageIndex, pageSize);
var byEmail = MemberService.FindMembersByEmail(emailToMatch, pageIndex, pageSize, out totalRecords, StringPropertyMatchType.Wildcard).ToArray();
//totalRecords = byEmail.Length;
//var pagedResult = new PagedResult<IMember>(totalRecords, pageIndex, pageSize);
var collection = new MembershipUserCollection();
foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize))
//foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize))
foreach (var m in byEmail)
{
collection.Add(m.AsConcreteMembershipUser());
}
@@ -227,12 +228,13 @@ namespace Umbraco.Web.Security.Providers
/// </returns>
public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
{
var byEmail = MemberService.FindMembersByUsername(usernameToMatch, StringPropertyMatchType.Wildcard).ToArray();
totalRecords = byEmail.Length;
var pagedResult = new PagedResult<IMember>(totalRecords, pageIndex, pageSize);
var byEmail = MemberService.FindMembersByUsername(usernameToMatch, pageIndex, pageSize, out totalRecords, StringPropertyMatchType.Wildcard).ToArray();
//totalRecords = byEmail.Length;
//var pagedResult = new PagedResult<IMember>(totalRecords, pageIndex, pageSize);
var collection = new MembershipUserCollection();
foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize))
//foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize))
foreach (var m in byEmail)
{
collection.Add(m.AsConcreteMembershipUser());
}

View File

@@ -343,12 +343,13 @@ namespace umbraco.providers.members
/// </returns>
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
{
var byEmail = ApplicationContext.Current.Services.MemberService.FindMembersByEmail(emailToMatch, StringPropertyMatchType.Wildcard).ToArray();
totalRecords = byEmail.Length;
var pagedResult = new PagedResult<IMember>(totalRecords, pageIndex, pageSize);
var byEmail = ApplicationContext.Current.Services.MemberService.FindMembersByEmail(emailToMatch, pageIndex, pageSize, out totalRecords, StringPropertyMatchType.Wildcard).ToArray();
//totalRecords = byEmail.Length;
//var pagedResult = new PagedResult<IMember>(totalRecords, pageIndex, pageSize);
var collection = new MembershipUserCollection();
foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize))
//foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize))
foreach (var m in byEmail)
{
collection.Add(ConvertToMembershipUser(m));
}
@@ -367,12 +368,13 @@ namespace umbraco.providers.members
/// </returns>
public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
{
var byEmail = ApplicationContext.Current.Services.MemberService.FindMembersByUsername(usernameToMatch, StringPropertyMatchType.Wildcard).ToArray();
totalRecords = byEmail.Length;
var pagedResult = new PagedResult<IMember>(totalRecords, pageIndex, pageSize);
var byEmail = ApplicationContext.Current.Services.MemberService.FindMembersByUsername(usernameToMatch, pageIndex, pageSize, out totalRecords, StringPropertyMatchType.Wildcard).ToArray();
//totalRecords = byEmail.Length;
//var pagedResult = new PagedResult<IMember>(totalRecords, pageIndex, pageSize);
var collection = new MembershipUserCollection();
foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize))
//foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize))
foreach (var m in byEmail)
{
collection.Add(ConvertToMembershipUser(m));
}