SqlKata provides the following methods to help executing your queries:
Get()
First()
FirstOrDefault()
Paginate()
Chunk()
By default calling the Get
method returns an IEnumerable<dynamic>
, giving you the max flexibility
var db = new QueryFactory(connection, new SqlServerCompiler());
IEnumerable<dynamic> users = db.Query("Users").Get();
However you can use the generic overload when you prefer strong types instead
IEnumerable<User> users = db.Query("Users").Get<User>();
use the First
or FirstOrDefault
to get the first record of the query
var book = db.Query("Books").Where("Id", 1).First<Book>();
Note: The
First
andFirstOrDefault
add theLimit(1)
clause implicitly to the query, so there is no need to add it by yourself.
To paginate your data, use the Paginate(pageNumber, perPage?)
method instead of Get
.
the Paginate
method accept two parameters, the page
number (1 based) and an optional perPage
that defaults to 25, and return an instance of type PaginationResult
.
The PaginationResult
expose the Each
property that implements the Enumerable
interface so you can safely iterate over the returned data.
// users is of type `PaginationResult`
var users = query.Paginate(1, 10);
foreach(var user in users.Each)
{
Console.WriteLine($"Id: {user.Id}, Name: {user.Name}");
}
You can call the Next
and Previous
methods to get the Next/Previous page respectively.
var page1 = query.Paginate(1);
foreach(var item in page1.Each)
{
// print items in the first page
}
var page2 = page1.Next(); // same as query.Paginate(2)
foreach(var item in page2.Each)
{
// print items in the 2nd page
}
Sometimes you may need to access the underlying queries for the next and previous methods. Use the NextQuery
and PreviousQuery
respectively in this case.
Accessing the queries can sometime more beneficial if you want more control, i.e. adding additional constraint.
var currentPage = query.Paginate(1, 10);
foreach(var item in currentPage.Each)
{
// print all books in the first page
}
var publishedInPage2 = currentPage.NextQuery().WhereTrue("IsPublished").Get();
foreach(var item in publishedInPage2.Each)
{
// print published books only in page 2
}
This example may not be used in real cases, use the Chunk method instead if you need such functionality
var currentPage = db.Query("Books").OrderBy("Date").Paginate(1);
while(currentPage.HasNext)
{
Console.WriteLine($"Looping over the page: {currentPage.Page}");
foreach(var book in currentPage.Each)
{
// process book
}
currentPage = currentPage.Next();
}
Sometimes you may want to retrieve data in chunks to prevent loading the whole table one time in memory, for this you can use the Chunk
method.
This is useful in situations where you have thousands of records.
query.Chunk(100, (rows, page) => {
Console.WriteLine($"Fetching page: {page}");
foreach(var row in rows)
{
// do something with row
}
});
To stop retrieving chunks simply use the Chunk(int chunkSize, Func<IEnumerable<dynamic>, int, bool> func)
overload and return false from the invoked action
query.Chunk(100, (rows, page) => {
// process rows
if(page == 3) {
// stop retrieving other chunks
return false;
}
// return true to continue
return true;
});
If you want to execute free raw statements, use the QueryFactory.Select
and QueryFactory.Statement
methods.
var users = db.Select("exec sp_get_users_by_date @date", new {date = DateTime.UtcNow});
QueryFactory.Statement
allows you to execute arbitrary statements like truncate table
, create database
, etc ...
db.Statement("truncate table Users");