mirror of
https://github.com/Microsoft/sql-server-samples.git
synced 2025-12-08 14:58:54 +00:00
Updated IVS example
Added SqlServer Rest API library, incremental pagination on server side processing page.
This commit is contained in:
@@ -1,123 +1,44 @@
|
||||
using Belgrade.SqlClient;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SqlClient;
|
||||
using SqlServerRestApi.Controller;
|
||||
using SqlServerRestApi.SQL;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// For more information on enabling Web API for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
|
||||
|
||||
namespace Catalog.Controllers
|
||||
namespace Register.Controllers
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
public class PeopleController : Controller
|
||||
{
|
||||
IQueryPipe sqlQuery = null;
|
||||
TableSpec tableSpec = new TableSpec("dbo.People", "name,surname,address,town");
|
||||
|
||||
public PeopleController(IQueryPipe sqlQueryService)
|
||||
{
|
||||
this.sqlQuery = sqlQueryService;
|
||||
}
|
||||
|
||||
// GET api/Company
|
||||
[HttpGet]
|
||||
public async Task Get(int draw, int start, int length)
|
||||
{
|
||||
Hashtable search = new Hashtable();
|
||||
|
||||
int i = 0;
|
||||
bool more = true;
|
||||
while (more)
|
||||
{
|
||||
if(Request.Query[$"columns[{i}][search][value]"].Count != 0)
|
||||
{
|
||||
search.Add(
|
||||
Request.Query[$"columns[{i}][data]"][0].ToString(),
|
||||
Request.Query[$"columns[{i}][search][value]"][0].ToString());
|
||||
i++;
|
||||
} else
|
||||
{
|
||||
more = false;
|
||||
}
|
||||
}
|
||||
|
||||
string orderCol;
|
||||
switch (Request.Query["order[0][column]"])
|
||||
{
|
||||
case "0": orderCol = "name"; break;
|
||||
case "1": orderCol = "surname"; break;
|
||||
case "2": orderCol = "address"; break;
|
||||
case "3": orderCol = "town"; break;
|
||||
default: orderCol = "name"; break;
|
||||
}
|
||||
|
||||
var orderDir = Request.Query["order[0][dir]"]=="asc"?"asc":"desc";
|
||||
|
||||
var sql = this.GetSearchQuery(search, orderCol, orderDir, start, length);
|
||||
|
||||
var header = System.Text.Encoding.UTF8.GetBytes( @"{
|
||||
""draw"":"+ draw + @",
|
||||
""recordsTotal"": "+ (start+length+1) + @",
|
||||
""recordsFiltered"": " + (start + length + 1) + @",
|
||||
""data"":");
|
||||
await Response.Body.WriteAsync(header,0,header.Length);
|
||||
|
||||
await sqlQuery.Stream(sql, Response.Body, "[]");
|
||||
|
||||
await Response.Body.WriteAsync(System.Text.Encoding.UTF8.GetBytes("}"),0,1);
|
||||
}
|
||||
|
||||
class SearchEntry
|
||||
{
|
||||
public string Column;
|
||||
public string Data;
|
||||
public override string ToString()
|
||||
{
|
||||
return Column + " LIKE @" + Column;
|
||||
}
|
||||
}
|
||||
|
||||
private SqlCommand GetSearchQuery(Hashtable search, string orderCol, string orderDir, int start, int length)
|
||||
{
|
||||
SqlCommand res = new SqlCommand();
|
||||
string sql = "select name, surname, address, town from people";
|
||||
IList<SearchEntry> l = new List<SearchEntry>(search.Count);
|
||||
foreach (DictionaryEntry entry in search)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(entry.Value.ToString()))
|
||||
{
|
||||
l.Add(new SearchEntry { Column = entry.Key.ToString(),
|
||||
Data = entry.Value.ToString()
|
||||
});
|
||||
res.Parameters.AddWithValue(entry.Key.ToString(), "%" + entry.Value.ToString() + "%");
|
||||
}
|
||||
}
|
||||
|
||||
if (l.Count > 0) {
|
||||
var predicate = string.Join(" and ", l as IEnumerable<SearchEntry>);
|
||||
sql += " where " + predicate;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(orderCol))
|
||||
{
|
||||
sql += " order by " + orderCol + " " + orderDir;
|
||||
}
|
||||
else
|
||||
{
|
||||
sql += " order by name ";
|
||||
}
|
||||
sql += string.Format(" OFFSET {0} ROWS FETCH NEXT {1} ROWS ONLY ", start, length);
|
||||
|
||||
res.CommandText = sql + " for json path";
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// GET api/Company
|
||||
[HttpGet("Load")]
|
||||
public async Task Load()
|
||||
/// <summary>
|
||||
/// Method that returns all data that will be processed by JQuery DataTables in client-side processing mode.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
// GET api/People/All
|
||||
[HttpGet("All")]
|
||||
public async Task GetAll()
|
||||
{
|
||||
await sqlQuery.Stream("select name, surname, address, town from people for json path, root('data')", Response.Body, @"{""data"":[]");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method that process server-side processing JQuery DataTables HTTP request
|
||||
/// and returns data that should be shown.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
// GET api/People
|
||||
[HttpGet]
|
||||
public async Task Get()
|
||||
{
|
||||
await this.ProcessJQueryDataTablesRequest(tableSpec, sqlQuery);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
using Belgrade.SqlClient;
|
||||
using Belgrade.SqlClient.SqlDb;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Data.SqlClient;
|
||||
using SqlServerRestApi;
|
||||
|
||||
namespace Catalog
|
||||
{
|
||||
@@ -26,15 +24,7 @@ namespace Catalog
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
string ConnString = Configuration["ConnectionStrings:IVSDemo"];
|
||||
|
||||
// Adding data access services/components.
|
||||
services.AddTransient<IQueryPipe>(
|
||||
sp => new QueryPipe(new SqlConnection(ConnString)));
|
||||
|
||||
services.AddTransient<ICommand>(
|
||||
sp => new Command(new SqlConnection(ConnString)));
|
||||
|
||||
services.AddSqlClient(Configuration["ConnectionStrings:IVSDemo"]);
|
||||
// Add framework services.
|
||||
services.AddMvc();
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"version": "1.0.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Belgrade.Sql.Client": "0.6.1",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
|
||||
@@ -15,7 +16,7 @@
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
|
||||
"Belgrade.Sql.Client": "0.6.0"
|
||||
"Sql-Server-Rest-Api": "0.1.4"
|
||||
},
|
||||
|
||||
"tools": {
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
<script src="media/js/lib/Bootstrap.js"></script>
|
||||
<script src="media/js/lib/jquery.dataTables.js"></script>
|
||||
<script src="media/js/lib/jquery.dataTables.Bootstrap.js"></script>
|
||||
|
||||
<script src="media/js/lib/jquery.dataTables.incremental_pagination.js"></script>
|
||||
|
||||
<script type="text/javascript" class="init">
|
||||
|
||||
$(document).ready(function() {
|
||||
@@ -28,15 +29,21 @@ $(document).ready(function() {
|
||||
|
||||
var table = $('#example').DataTable(
|
||||
{
|
||||
"ajax": "/api/People/Load",
|
||||
"ajax": "/api/People/All",
|
||||
"columns": [
|
||||
{ "data": "name", "width": "10%" },
|
||||
{ "data": "surname", "width": "10%" },
|
||||
{ "data": "address", "width": "50%" },
|
||||
{ "data": "town", "width": "10%" }
|
||||
],
|
||||
"sDom": "lrtp",
|
||||
"pagingType": "simple"
|
||||
"pagingType": "simple_numbers",
|
||||
"language": {
|
||||
"lengthMenu": "Display _MENU_ per page",
|
||||
"zeroRecords": "Nothing found - sorry",
|
||||
"info": "Page _PAGE_",
|
||||
"infoEmpty": "No records available",
|
||||
"infoFiltered": ""
|
||||
}
|
||||
});
|
||||
|
||||
// Apply the search
|
||||
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
$.fn.dataTableExt.oPagination.incremental = {
|
||||
/*
|
||||
* Function: oPagination.incremental.fnInit
|
||||
* Purpose: Initalise dom elements required for pagination with a list of the pages
|
||||
* Returns: -
|
||||
* Inputs: object:oSettings - dataTables settings object
|
||||
* node:nPaging - the DIV which contains this pagination control
|
||||
* function:fnCallbackDraw - draw function which must be called on update
|
||||
*/
|
||||
"fnInit": function (oSettings, nPaging, fnCallbackDraw) {
|
||||
$(nPaging).prepend($("<ul class=\"pagination\"></ul>"));
|
||||
var ul = $("ul", $(nPaging));
|
||||
nFirst = document.createElement('li');
|
||||
nPrevious = document.createElement('li');
|
||||
nNext = document.createElement('li');
|
||||
|
||||
$(nPrevious).append($('<span>' + (oSettings.oLanguage.oPaginate.sPrevious) + '</span>'));
|
||||
$(nFirst).append($('<span>1</span>'));
|
||||
$(nNext).append($('<span>' + (oSettings.oLanguage.oPaginate.sNext) + '</span>'));
|
||||
|
||||
nFirst.className = "paginate_button first active";
|
||||
nPrevious.className = "paginate_button previous";
|
||||
nNext.className = "paginate_button next";
|
||||
|
||||
|
||||
ul.append(nPrevious);
|
||||
ul.append(nFirst);
|
||||
ul.append(nNext);
|
||||
|
||||
$(nFirst).click(function () {
|
||||
oSettings.oApi._fnPageChange(oSettings, "first");
|
||||
fnCallbackDraw(oSettings);
|
||||
});
|
||||
|
||||
$(nPrevious).click(function () {
|
||||
if (!(oSettings._iDisplayStart === 0)) {
|
||||
oSettings.oApi._fnPageChange(oSettings, "previous");
|
||||
fnCallbackDraw(oSettings);
|
||||
}
|
||||
});
|
||||
|
||||
$(nNext).click(function () {
|
||||
if (!(oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay()
|
||||
||
|
||||
oSettings.aiDisplay.length < oSettings._iDisplayLength)) {
|
||||
oSettings.oApi._fnPageChange(oSettings, "next");
|
||||
fnCallbackDraw(oSettings);
|
||||
}
|
||||
});
|
||||
|
||||
/* Disallow text selection */
|
||||
$(nFirst).bind('selectstart', function () { return false; });
|
||||
$(nPrevious).bind('selectstart', function () { return false; });
|
||||
$(nNext).bind('selectstart', function () { return false; });
|
||||
|
||||
// Reset dynamically generated pages on length/filter change.
|
||||
$(oSettings.nTable).DataTable().on('length.dt', function (e, settings, len) {
|
||||
$("li.dynamic_page_item", nPaging).remove();
|
||||
});
|
||||
|
||||
$(oSettings.nTable).DataTable().on('search.dt', function (e, settings, len) {
|
||||
$("li.dynamic_page_item", nPaging).remove();
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* Function: oPagination.incremental.fnUpdate
|
||||
* Purpose: Update the list of page buttons shows
|
||||
* Returns: -
|
||||
* Inputs: object:oSettings - dataTables settings object
|
||||
* function:fnCallbackDraw - draw function which must be called on update
|
||||
*/
|
||||
"fnUpdate": function (oSettings, fnCallbackDraw) {
|
||||
if (!oSettings.aanFeatures.p) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Loop over each instance of the pager */
|
||||
var an = oSettings.aanFeatures.p;
|
||||
for (var i = 0, iLen = an.length ; i < iLen ; i++) {
|
||||
var buttons = an[i].getElementsByTagName('li');
|
||||
$(buttons).removeClass("active");
|
||||
|
||||
if (oSettings._iDisplayStart === 0) {
|
||||
buttons[0].className = "paginate_buttons disabled previous";
|
||||
buttons[buttons.length - 1].className = "paginate_button enabled next";
|
||||
} else {
|
||||
buttons[0].className = "paginate_buttons enabled previous";
|
||||
}
|
||||
|
||||
var page = Math.round(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1;
|
||||
if (page == buttons.length-1 && oSettings.aiDisplay.length > 0) {
|
||||
$new = $('<li class="dynamic_page_item active"><span>' + page + "</span></li>");
|
||||
$(buttons[buttons.length - 1]).before($new);
|
||||
$new.click(function () {
|
||||
$(oSettings.nTable).DataTable().page(page-1);
|
||||
|
||||
fnCallbackDraw(oSettings);
|
||||
});
|
||||
} else
|
||||
$(buttons[page]).addClass("active");
|
||||
|
||||
if (oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay()
|
||||
||
|
||||
oSettings.aiDisplay.length < oSettings._iDisplayLength) {
|
||||
buttons[buttons.length - 1].className = "paginate_button disabled next";
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -17,6 +17,7 @@
|
||||
<script src="media/js/lib/Bootstrap.js"></script>
|
||||
<script src="media/js/lib/jquery.dataTables.js"></script>
|
||||
<script src="media/js/lib/jquery.dataTables.Bootstrap.js"></script>
|
||||
<script src="media/js/lib/jquery.dataTables.incremental_pagination.js"></script>
|
||||
|
||||
|
||||
<script type="text/javascript" class="init">
|
||||
@@ -32,15 +33,21 @@ $(document).ready(function() {
|
||||
var table = $('#example').DataTable({
|
||||
"serverSide": true,
|
||||
"processing": true,
|
||||
"sDom": "lrtp",
|
||||
"pagingType": "simple",
|
||||
"pagingType": "incremental",
|
||||
"ajax": "/api/People",
|
||||
"columns": [
|
||||
{ "data": "name", "width": "10%" },
|
||||
{ "data": "surname", "width": "10%" },
|
||||
{ "data": "address", "width": "50%" },
|
||||
{ "data": "town", "width": "10%" }
|
||||
]
|
||||
],
|
||||
"language": {
|
||||
"lengthMenu": "Display _MENU_ per page",
|
||||
"zeroRecords": "Nothing found - sorry",
|
||||
"info": "Page _PAGE_",
|
||||
"infoEmpty": "No records available",
|
||||
"infoFiltered": ""
|
||||
}
|
||||
});
|
||||
|
||||
// Apply the search
|
||||
|
||||
Reference in New Issue
Block a user