Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggested implementation for ToProjectedPage() #635

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/NPoco/Linq/ComplexSqlBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,24 @@ public Sql GetSqlForProjection<T2>(Expression<Func<T, T2>> projectionExpression,
var sql = BuildJoin(_database, _sqlExpression, _joinSqlExpressions.Values.ToList(), selectMembers, false, distinct);
return sql;
}
public Sql GetSqlForProjection<T2>(Expression<Func<T, T2>> projectionExpression, bool distinct, int skip, int rows)
{
var selectMembers = _database.DatabaseType.ExpressionVisitor<T>(_database, _pocoData).SelectProjection(projectionExpression);

((ISqlExpression)_sqlExpression).SelectMembers.Clear();
((ISqlExpression)_sqlExpression).SelectMembers.AddRange(selectMembers);

_sqlExpression.Limit(skip, rows);

if (!_joinSqlExpressions.Any())
{
var finalsql = ((ISqlExpression)_sqlExpression).ApplyPaging(_sqlExpression.Context.ToSelectStatement(false, distinct), selectMembers.Select(x => x.PocoColumns), _joinSqlExpressions);
return new Sql(finalsql, _sqlExpression.Context.Params);
}

var sql = BuildJoin(_database, _sqlExpression, _joinSqlExpressions.Values.ToList(), selectMembers, false, distinct);
return sql;
}
public Sql BuildJoin(IDatabase database, SqlExpression<T> sqlExpression, List<JoinData> joinSqlExpressions, List<SelectMember> newMembers, bool count, bool distinct)
{
var modelDef = _pocoData;
Expand Down
52 changes: 51 additions & 1 deletion src/NPoco/Linq/SimpleQueryProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public interface IAsyncQueryResultProvider<T>
Task<bool> Any(Expression<Func<T, bool>> whereExpression);
Task<Page<T>> ToPage(int page, int pageSize);
Task<List<T2>> ProjectTo<T2>(Expression<Func<T, T2>> projectionExpression);
Task<Page<T2>> ToProjectedPage<T2>(Expression<Func<T, T2>> projectionExpression, int page, int pageSize);
Task<List<T2>> Distinct<T2>(Expression<Func<T, T2>> projectionExpression);
Task<List<T>> Distinct();
}
Expand All @@ -53,6 +54,7 @@ public interface IQueryResultProvider<T>
Page<T> ToPage(int page, int pageSize);
List<T2> ProjectTo<T2>(Expression<Func<T, T2>> projectionExpression);
List<T2> Distinct<T2>(Expression<Func<T, T2>> projectionExpression);
Page<T2> ToProjectedPage<T2>(Expression<Func<T, T2>> projectionExpression, int page, int pageSize);
List<T> Distinct();
Task<List<T>> ToListAsync();
Task<T[]> ToArrayAsync();
Expand All @@ -71,6 +73,7 @@ public interface IQueryResultProvider<T>
Task<bool> AnyAsync(Expression<Func<T, bool>> whereExpression);
Task<Page<T>> ToPageAsync(int page, int pageSize);
Task<List<T2>> ProjectToAsync<T2>(Expression<Func<T, T2>> projectionExpression);
Task<Page<T2>> ToProjectedPageAsync<T2>(Expression<Func<T, T2>> projectionExpression, int page, int pageSize);
Task<List<T2>> DistinctAsync<T2>(Expression<Func<T, T2>> projectionExpression);
Task<List<T>> DistinctAsync();
}
Expand Down Expand Up @@ -338,7 +341,29 @@ public Task<List<T2>> ProjectTo<T2>(Expression<Func<T, T2>> projectionExpression
var sql = _buildComplexSql.GetSqlForProjection(projectionExpression, false);
return ExecuteQueryAsync(sql).Select(projectionExpression.Compile()).ToListAsync().AsTask();
}
public async Task<Page<T2>> ToProjectedPage<T2>(Expression<Func<T, T2>> projectionExpression, int page, int pageSize)
{
int offset = (page - 1) * pageSize;

// Save the one-time command time out and use it for both queries
int saveTimeout = _database.OneTimeCommandTimeout;

// Setup the paged result
var result = new Page<T2>();
result.CurrentPage = page;
result.ItemsPerPage = pageSize;
result.TotalItems = await Count().ConfigureAwait(false);
result.TotalPages = result.TotalItems / pageSize;
if ((result.TotalItems % pageSize) != 0)
result.TotalPages++;

_database.OneTimeCommandTimeout = saveTimeout;

var sql = _buildComplexSql.GetSqlForProjection(projectionExpression, false, offset, pageSize);
result.Items = await ExecuteQueryAsync(sql).Select(projectionExpression.Compile()).ToListAsync().AsTask();

return result;
}
public Task<List<T>> Distinct()
{
return ExecuteQueryAsync(new Sql(_sqlExpression.Context.ToSelectStatement(true, true), _sqlExpression.Context.Params)).ToListAsync().AsTask();
Expand Down Expand Up @@ -606,7 +631,29 @@ public QueryProvider(Database database) : base(database, null)
var sql = _buildComplexSql.GetSqlForProjection(projectionExpression, false);
return ExecuteQuery(sql).Select(projectionExpression.Compile()).ToList();
}
public new Page<T2> ToProjectedPage<T2>(Expression<Func<T, T2>> projectionExpression, int page, int pageSize)
{
int offset = (page - 1) * pageSize;

// Save the one-time command time out and use it for both queries
int saveTimeout = _database.OneTimeCommandTimeout;

// Setup the paged result
var result = new Page<T2>();
result.CurrentPage = page;
result.ItemsPerPage = pageSize;
result.TotalItems = Count();
result.TotalPages = result.TotalItems / pageSize;
if ((result.TotalItems % pageSize) != 0)
result.TotalPages++;

_database.OneTimeCommandTimeout = saveTimeout;

var sql = _buildComplexSql.GetSqlForProjection(projectionExpression, false, page, pageSize);
result.Items = ExecuteQuery(sql).Select(projectionExpression.Compile()).ToList();

return result;
}
public new List<T2> Distinct<T2>(Expression<Func<T, T2>> projectionExpression)
{
var sql = _buildComplexSql.GetSqlForProjection(projectionExpression, true);
Expand Down Expand Up @@ -727,7 +774,10 @@ public Task<List<T2>> DistinctAsync<T2>(Expression<Func<T, T2>> projectionExpres
{
return base.Distinct(projectionExpression);
}

public Task<Page<T2>> ToProjectedPageAsync<T2>(Expression<Func<T, T2>> projectionExpression, int skip, int rows)
{
return base.ToProjectedPage(projectionExpression, skip, rows);
}
public Task<List<T>> DistinctAsync()
{
return base.Distinct();
Expand Down
8 changes: 7 additions & 1 deletion test/NPoco.Tests/Async/QueryAsyncTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@ public async Task FetchByExpressionAndSelect()
var users = await Database.Query<User>().ProjectToAsync(x => new { x.Name });
Assert.AreEqual("Name1", users[0].Name);
}

[Test]
public async Task FetchByExpressionAndSelectProjection()
{
var records = await Database.Query<User>().ToProjectedPageAsync(x => new { x.Name }, 2, 5);
Assert.AreEqual(records.Items.Count, 5);
Assert.AreEqual(records.Items[0].Name, "Name6");
}
[Test]
public async Task PagingAsync()
{
Expand Down