'Mapping relationships using PetaPoco paging
I am using PetaPoco v5.1.228.0 and I am trying to fetch a list of people along with the category they belong to, using paging (30 items per page).
This is my code:
IEnumerable<Person> people;
var sql = new Sql("SELECT * FROM Person p INNER JOIN Category c ON p.CategoryId = c.Id");
using (var db = GetDatabaseConnection()) {
var paging = db.Page<Person>(currentPage, 30, sql);
people = paging.Items;
}
Person.cs
public class Person {
public int Id { get; set; }
public string Name { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
}
Category.cs
public class Category {
public int Id { get; set; }
public string Name { get; set; }
}
The problem is it won't populate the Category property within the Person object. As far as I know only db.Fetch
allows multiple types to be specified, but in this case I would need to code the paging functionality myself.
What would be the best way to do it?
Solution 1:[1]
You can do it with an extention metod over IDatabase:
public static Page<TRet> PagedFetch<T1, T2, TRet>(this PetaPoco.IDatabase db, long page, long itemsPerPage, Func<T1, T2, TRet> cb, string sql, params object[] args)
{
SQLParts parts;
if (!db.Provider.PagingUtility.SplitSQL(sql, out parts))
throw new Exception("Unable to parse SQL statement for paged query");
db.Provider.BuildPageQuery((page - 1) * itemsPerPage, itemsPerPage, parts, ref args);
sql = string.Format("{0} offset {1} rows fetch next {2} rows only", sql, (page - 1) * itemsPerPage, itemsPerPage);
var data = db.Fetch(cb, sql, args);
var result = new Page<TRet>
{
Items = data,
TotalItems = db.ExecuteScalar<long>(parts.SqlCount),
CurrentPage = page,
ItemsPerPage = itemsPerPage
};
result.TotalPages = result.TotalItems / itemsPerPage;
if ((result.TotalItems % itemsPerPage) != 0)
result.TotalPages++;
return result;
}
Solution 2:[2]
@Andres R: Useful answer, but code works for MSSQL only. Use this: string.Format("{0} LIMIT {2} OFFSET {1}", ...) for MySQL/SQLite/PostgreSQL/MSSQL 2012+.
It took me also some time to find how to use the Func<T1, T2, TRet> cb parameter, which is not covered in PetaPoco Fetch() documentation. It is a function, which simply fills your final entity with related entities from joined tables. Here is than an usage example
var page = PagedFetch<DataSet, User, DataSet>(
page,
itemsPerPage,
(ds, usr) => { ds.user = usr; return ds; },
sql,
whereArguments);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Andres R |
Solution 2 |