在處理一些大量數據時,往往用到查詢,但是大量數據不適合全部查出,最好是分頁查出,分頁時還想有些參數過濾下,如下效果
First 定義一個遠端查詢的store
Ext.define('項目包名.路徑.store類名', {
extend: 'Ext.data.Store',
alias: 'store.remoteDemo',//指定store的別名
idProperty: '列名',
fields: [
//fields配置參數
],
remoteSort: true,//重要 指定遠端排序
remoteFilter: true,//!!重要 指定遠端過濾
pageSize:20,//指定一頁行數 默認是25
proxy: {
type: 'ajax',//指定代理爲ajax 通過服務端處理
api: 'url地址'
}
});
Second 前端控件引用store,並寫好過濾處理
例如grid控件:在grid控件上放個可輸入的文本框 用於遠端查詢過濾
{
xtype:'grid',
items:[
{
xtype:'toolbar',
itemId:'tbar',
docked: 'top',
items:[
{
xtype:'textfield',
name:'paramA',//自定義要查詢的參數的key
role: 'filter',//可以設置一個role字段來標識
placeholder:'查詢條件1'
},
{
xtype:'textfield',
name:'paramB',
role: 'filter',
placeholder:'查詢條件2'
},
{
xtype:'button',
text:'查詢',
handler:'onSearch'//當點擊查詢時調用store的過濾查詢
}
]
}
],
plugins: {
gridpagingtoolbar: true//使用分頁插件 必備
},
store:{
type:'remoteDemo'//指定第一步配置的store
},
}
設置store查詢方法處理
onSearch() {
let grid = 通過lookup或其他查詢器找到grid控件,
store = grid.getStore(),//獲取store
filters = [];
let vals;
const bar = grid.down('#tbar'),
fields = bar.query('field[role=filter]');//通過查詢器獲取用於輸入過濾條件的控件
vals = {};
fields.forEach(field => {
vals[field.getName()] = field.getValue();
});
for (var k in vals) {
if (vals.hasOwnProperty(k) && !Ext.isEmpty(vals[k])) {
filters.push({ //以鍵值對的形式 組成後端所需的 過濾json
property: k,
value: vals[k]
});
}
}
store.suppressNextFilter = true;
store.clearFilter(true);//清除上次的過濾 防止數據錯誤
store.setFilters(filters);//加載新的過濾條件
store.suppressNextFilter = false;
store.loadPage(1);//加載第一頁
}
Third 服務端處理過濾條件,組織查詢語句
後端用的C# 自己可以參照改造,反正前端傳回的值都是 json格式的
定義好一個PageQueryXX方法名的方法(爲何要PageQuery打頭? ——容易辨識)
public StoreResult PageQuerySqlLog(StoreParams storeParams)//使用StoreResult 作爲返回類型,StoreParams 類型用於接收store的各種參數
{
string where = @"";
List < SqlParameter > parameters = new List<SqlParameter>();
if (storeParams.filter != null) {
foreach(StoreFilter filter in storeParams.filter)//讀取store的filter裏的json信息
{
if (string.IsNullOrEmpty(filter.value)) continue;
if (filter.property == "paramA") {
where += @" and T.表列名 like '%' + @參數名A + '%'";//拼接sql查詢語句
parameters.Add(new SqlParameter("@參數名A", filter.value));//爲參數賦值
}
else if (filter.property == "paramB") {
where += @" and T.表列名 >= @DateFr";//時間格式的demo
SqlParameter pa = new SqlParameter("@DateFr", SqlDbType.DateTime);
pa.Value = DateTime.Parse(filter.value);
parameters.Add(pa);
}
}
}
//拼裝分頁查詢的子查詢語句
string innerSql = string.Format(@" select 列名A,列名B from 表名 T where { 0 } ", where);//把動態拼接的where條件塞入
DataTable dt = null;
//拼接分頁查詢
//!!注意: 如果想要查出滿足條件的總數 在sqlSERVER中可以用 COUNT(1) OVER() as TotalCount 以在分頁查詢時 也統計到所有總數
//不理解此句話就接着往下看文章
string sql = @"
Select S1.*, TotalCount
From(
select ROW_NUMBER() OVER(order by S.DocKey desc) as RowNum, COUNT(1) OVER() as TotalCount, S.*
from
(
" + innerSql + @"
) S
) S1
where S1.RowNum >= @start And S1.RowNum <= @end
";
SqlCommand command = new SqlCommand();
command.CommandText = sql;
command.Parameters.AddWithValue("@start", storeParams.start + 1);
command.Parameters.AddWithValue("@end", storeParams.start + storeParams.limit);
foreach(SqlParameter pa in parameters)
{
command.Parameters.Add(pa);
}
dt = ConnectionManager.ExecuteDataTable(command);
StoreResult result = new StoreResult();
result.root = dt;
if (dt != null && dt.Rows.Count > 0)
result.total = TypeHelper.GetIntValue(dt.Rows[0]["TotalCount"]);//將實際行數返回 不需要實際行數 就可以用下面 的Int32.MaxValue;
else result.total = 0;
//若是無需知道總數 可以用 result.total = Int32.MaxValue;
//一般前端用的list或dataview控件 就不關心實際總數 返回result.total 值 只是用於在前端可以展示 分頁
return result;
}
自己定義了兩個store的幫助類
一個是返回結果的類
namespace 命名空間
{
[Serializable]
public class StoreResult
{
public int total;
public object root;
public object footer;
}
}
另一個是store參數的類
namespace 命名空間
{
[Serializable]
public class StoreParams
{
public int page;
public int start;
public int limit;
public string query; //自動完成參數
public List<StoreGrouper> group;
public List<StoreSorter> sort;
public List<StoreFilter> filter;
}
[Serializable]
public class StoreGrouper
{
public string property;
public string direction;
}
[Serializable]
public class StoreSorter
{
public string property;
public string direction;
}
[Serializable]
public class StoreFilter
{
public string property;
private string op;
[JsonProperty("operator")]
public string Operator
{
get
{
return op;
}
set
{
if (string.IsNullOrEmpty(value))
{
if (value == "!=") op = "<>";
else op = value;
}
else
{
throw WarningException.Parse("過濾器操作符{0}不合法", value);
}
}
}
public string value;
}
}
其他情況:
A: 前端控件使用的是list
list使用的分頁加載是不關心store的總數的,僅僅是爲了出現“加載更多”字樣
那後端在做分頁查詢處理時,若是無需查出真實總數,可以用
StoreResult result = new StoreResult();
result.total = Int32.MaxValue;// 直接用個最大常量 即可
B: 前端控件使用的是Grid
如果這時還是直接返回Int32.MaxValue的話,grid的分頁就會出現如下情況:
返回的不是實際總頁數,這樣會翻出很多空白頁
這時,應該在查詢分頁數時,就將總條數一併查出,使用
COUNT(1) OVER () as TotalCount
一種完整的sql分頁查詢,連同分頁行總數一併查出來了
Select S1.*,TotalCount
From (
select ROW_NUMBER() OVER (order by S.DocKey desc) as RowNum,COUNT(1) OVER () as TotalCount, S.*
from
(
" + innerSql + @"
) S
) S1
where S1.RowNum >= @start And S1.RowNum <= @end
再返回前端總數值時 把查到的TotalCount 返回即可