1 為什麼邏輯分頁不使用分布式緩存進行存儲?
1、首先必須明白邏輯分頁不使用分布式緩存進行存儲不是技術層面的因素,在技術層面完全可以把邏輯分頁資料通過分布式緩存資料庫進行存儲和管理。
2、由于邏輯分頁操作需要頻繁的把資料庫指定表中的持久化資料加載到記憶體中,以便程式使用,如果再把這些資料通過分布式緩存資料庫進行存儲和管理,不但不能達能增加程式響應速度的目的,反而有極大機率上會增加記憶體消耗拖慢程式的響應速度的反效果。
3、如果把邏輯分頁操作所産生的資料通過分布式緩存資料庫進行存儲和管理,由于短時間内不會對記憶體中的資料進行銷毀,導緻持續不斷的增加記憶體資源的消耗,會由于記憶體資源的耗盡,進而會造成記憶體的溢出,最終作業系統的崩潰,這種現象在基于網絡實作的程式上會以驚人的速度呈現出來。這是邏輯分頁不使用分布式緩存進行存儲的實體因素。
4、使用分布式緩存資料庫進行存儲和管理的持久化資料的基本指導性原則有:在短時間内持久化資料不會發生改變,且不能頻繁的加載到記憶體;例如:登入操作執行後的使用者資訊資料、角色實體的執行個體、産品類型實體的執行個體等;與之相對的則是:使用者所有執行個體的分頁操作、産品所有執行個體的分頁操作等。
5、其實在Vue中的全局存儲(store/index.js)也是一種特殊的用分布式緩存資料庫進行存儲和管理的技術實作,因為它也是通過鍵/值所建構的緩存項把登入操作執行後的使用者資訊資料、角色實體的執行個體、産品類型實體的執行個體等資料在一段時間記憶體儲在記憶體中并進行相應的管理工作。二者隻有應用場景的差別而無技術實質的差別:一個用于後端程式資料的存儲和管理;另有用于前端程式資料的存儲和管理。
2 Services.Customers.CustomerService.GetAllCustomersAsync
/// <param name="email">1個指定的電字郵箱字元串,預設值:null,即該參數執行個體不參與篩選操作。</param>
/// <param name="name">1個指定的使用者名/昵稱,預設值:null,即該參數執行個體不參與篩選操作。</param>
/// <param name="phone">個指定的手機号,預設值:null,即該參數執行個體不參與篩選操作。</param>
/// <param name="isSystemAccount">訓示是否隻擷取是系統帳戶的所有執行個體,預設值:null,即該參數執行個體不參與篩選操作。</param>
/// <param name="isActive">訓示是否隻擷取已經處于激活狀态的所有執行個體,預設值:null,即該參數執行個體不參與篩選操作。</param>
/// <param name="isDeleted">訓示是否隻擷取已經處于邏輯删除狀态的所有執行個體,預設值:null,即該參數執行個體不參與篩選操作。</param>
/// <param name="orderByFiled">1個指定的用于排序操作的排序字段字元串,預設值:null,即按照建立時間以倒序方式進行排序操作。</param>
/// <param name="orderByType">1個指定的用于排序操作的排序排序方式,預設值:null,即按照建立時間以倒序方式進行排序操作。</param>
/// <param name="pageIndex">目前頁的頁數值(與“pageSize”結合,設定需要跳過指定實體執行個體的個數值),預設值:0,即不需要執行跳過操作。</param>
/// <param name="pageSize">分頁操作中每頁最多顯示執行個體的項(行)數值(與“pageIndex”結合,設定需要跳過指定實體執行個體的個數值),預設值:int.MaxValue=2147483647。</param>
/// <summary>
/// 【異步擷取所有使用者】
/// <remarks>
/// 摘要:
/// 根據前端分頁元件傳遞的參數執行個體,擷取符合條件的使用者表1指定頁面内的持久化資料加載到1指定記憶體邏輯頁面内。
/// 說明:
/// 該方法沒有定義緩存操作,更沒有定義緩存的移除操作。
/// </remarks>
/// <returns>
/// 傳回:
/// 1指定記憶體邏輯頁面内的使用者實體的所有執行個體。
/// </returns>
/// </summary>
public virtual async Task<IPagedList<Customer>> GetAllCustomersAsync(string email = null, string name = null,
string phone = null, bool? isSystemAccount = null, bool? isActive = null, bool? isDeleted = null,
string orderByFiled = null, string orderByType = null, long pageIndex = 0, int pageSize = int.MaxValue)
{
return await _customerRepository.GetAllPagedAsync(query =>
{
//根據參數執行個體,執行篩選操作。
if (!string.IsNullOrWhiteSpace(email))
query = query.Where(customer => customer.Email.Contains(email));
if (!string.IsNullOrWhiteSpace(name))
query = query.Where(customer => customer.Name.Contains(name));
if (!string.IsNullOrWhiteSpace(phone))
query = query.Where(customer => customer.Phone.Contains(phone));
if (isSystemAccount.HasValue)
query = query.Where(customer => customer.IsSystemAccount == isSystemAccount);
if (isActive.HasValue)
query = query.Where(customer => customer.IsActive == isActive);
if (isDeleted.HasValue)
query = query.Where(customer => customer.Deleted == isDeleted);
//根據參數執行個體,執行排序操作。
if (string.IsNullOrWhiteSpace(orderByFiled) && string.IsNullOrWhiteSpace(orderByType))
{
query = query.OrderByDescending(customer => customer.CreatedDateTime);
}
else if (!string.IsNullOrWhiteSpace(orderByFiled))
{
if (orderByType.Equals("ascending", StringComparison.InvariantCultureIgnoreCase))
{
query.OrderBy(orderByFiled);
}
else if (orderByType.Equals("descending", StringComparison.InvariantCultureIgnoreCase))
{
query.OrderByDescending(orderByFiled);
}
}
return query;
}, pageIndex, pageSize);
}
3 WebApi.Models.Customer.CustomerSearchModel
namespace WebApi.Models.Customer
{
/// <summary>
/// 【使用者過濾篩選模型--紀錄】
/// <remarks>
/// 摘要:
/// 通過該紀錄中的屬性成員執行個體為指定資料庫中的使用者表的過濾篩選操作提供資料支撐。
/// </remarks>
/// </summary>
public record CustomerSearchModel
{
/// <summary>
/// 【使用者名】
/// <remarks>
/// 摘要:
/// 擷取/設定1個指定的使用者名(賬戶、昵稱)。
/// 說明:
/// 為使該屬性的執行個體有可能不參與排序操作,該屬性的預設執行個體被設定為:null。
/// </remarks>
/// </summary>
public string Name { get; set; } = null;
/// <summary>
/// 【電子郵箱】
/// <remarks>
/// 摘要:
/// 擷取/設定1個指定使用者所對應的電子郵箱。
/// 說明:
/// 為使該屬性的執行個體有可能不參與排序操作,該屬性的預設執行個體被設定為:null。
/// </remarks>
/// </summary>
public string Email { get; set; } = null;
/// <summary>
/// 【手機号】
/// <remarks>
/// 摘要:
/// 擷取/設定1個指定使用者所對應的手機号。
/// 說明:
/// 為使該屬性的執行個體有可能不參與排序操作,該屬性的預設執行個體被設定為:null。
/// </remarks>
/// </summary>
public string Phone { get; set; } = null;
/// <summary>
/// 【系統帳戶?】
/// <remarks>
/// 摘要:
/// 擷取/設定1個值false(預設值:不是)/true(是),該值訓示使用者實體的1個指定執行個體是否是系統帳戶。
/// 說明:
/// 1、為使該屬性的執行個體有可能不參與過濾篩選操作,該屬性被定義為了可空類型且預設執行個體被設定為:null。
/// 2、如果是系統帳戶,則該使用者将不能被實體/邏輯删除,即在删除操作中會通過該屬性執行個體過濾掉系統帳戶的所有使用者。
/// </remarks>
/// </summary>
public bool? IsSystemAccount { get; set; }= null;
/// <summary>
/// 【啟用?】
/// <remarks>
/// 摘要:
/// 擷取/設定1個值false(禁用)/true(預設值:啟用),該值訓示使用者實體的1個指定執行個體是否處于啟用狀态。
/// 說明:
/// 1、為使該屬性的執行個體有可能不參與過濾篩選操作,該屬性被定義為了可空類型且預設執行個體被設定為:null。
/// </remarks>
/// </summary>
public bool? IsActive { get; set; } = null;
/// <summary>
/// 【(邏輯)删除?】
/// <remarks>
/// 摘要:
/// 擷取/設定1個值false(未(邏輯)删除)/true(已經(邏輯)删除),該值訓示使用者實體的1個指定執行個體是否已經處于(邏輯)删除狀态。
/// 說明:
/// 1、為使該屬性的執行個體有可能不參與過濾篩選操作,該屬性被定義為了可空類型且預設執行個體被設定為:null。
/// </remarks>
/// </summary>
public bool? IsDeleted { get; set; } = null;
}
}
4 WebApi.Models.OrderByModel
namespace WebApi.Models
{
/// <summary>
/// 【排序模型--紀錄】
/// <remarks>
/// 摘要:
/// 通過該紀錄中的屬性成員執行個體為指定資料庫中的指定表的排序操作提供資料支撐。
/// </remarks>
/// </summary>
public record OrderByModel
{
/// <summary>
/// 【排序字段】
/// <remarks>
/// 摘要:
/// 擷取/設定1個指定的用于排序操作的字段。
/// 說明:
/// 為使該屬性的執行個體有可能不參與排序操作,該屬性的預設執行個體被設定為:null。
/// </remarks>
/// </summary>
public string OrderByFiled { get; set; } = null;
/// <summary>
/// <summary>
/// 【排序方式】
/// <remarks>
/// 摘要:
/// 擷取/設定1個指定的用于操作操作的排序方式:正序/倒序。
/// 說明:
/// 為使該屬性的執行個體有可能不參與排序操作,該屬性的預設執行個體被設定為:null。
/// </remarks>
/// </summary>
public string OrderByType { get; set; } = null;
}
}
5 WebApi.Controllers.CustomerController.Index
/// <param name="pagination">分頁模型紀錄的1個指定執行個體。</param>
/// <summary>
/// 【使用者表單單擊送出分頁--需權限】
/// </summary>
/// <remarks>
/// 摘要:
/// 通過分頁控件所傳遞的參數執行個體,擷取符合條件的1指定頁面内的所有資料,為指定頁面的渲染顯示提供資料支撐。
/// 注意:
/// 表單送出分頁必須使用“[HttpPost]”進行标記。
/// </remarks>
/// <returns>
/// 傳回:
/// 消息模型紀錄的1個指定執行個體,該執行個體存儲目前“Api”方法的執行操作結果,為用戶端頁面的渲染提供資料支撐。
/// </returns>
//[Authorize(Policy = "OnlyInAdministrator")]
//[Authorize(PermissionsPolicy.Name)]
[HttpPost]
public async Task<MessageModel<PageModel<Customer>>> Index([FromBody] PaginationModel pagination)
{
CustomerSearchModel _customerSearchModel = new CustomerSearchModel();
if (!string.IsNullOrEmpty(pagination.QueryCondition))
_customerSearchModel = JsonConvert.DeserializeAnonymousType(pagination.QueryCondition, _customerSearchModel);
OrderByModel _orderByModel = new OrderByModel();
if (!string.IsNullOrEmpty(pagination.OrderByModel))
_orderByModel = JsonConvert.DeserializeAnonymousType(pagination.OrderByModel, _orderByModel);
//根據前端分頁元件傳遞的參數執行個體,從角色表中擷取(1邏輯頁中的)相應行數的資料,并把這些資料存儲到清單執行個體中。
IPagedList<Customer> _customerPageList = await _customerService.GetAllCustomersAsync(_customerSearchModel.Email,
_customerSearchModel.Name,
_customerSearchModel.Phone,
_customerSearchModel.IsSystemAccount,
_customerSearchModel.IsActive,
_customerSearchModel.IsDeleted,
_orderByModel.OrderByFiled,
_orderByModel.OrderByType,
(pagination.PageIndex - 1),
pagination.PageSize);
//執行個體化目前模型頁(“實體頁”),為目前頁面的渲染顯示提供資料支撐。
PageModel<Customer> _customerPageModel = new PageModel<Customer>()
{
PageIndex = pagination.PageIndex,
PageSize = pagination.PageSize,
TotalCount = _customerPageList.TotalCount,
Data = _customerPageList,
};
//執行個體化消息模型錄,對目前“Api”控制器行方法的執行操作結果進行存儲,為用戶端頁面的渲染提供資料支撐。
return MessageModel<PageModel<Customer>>.GetSuccess($"成功擷取第{pagination.PageIndex}頁内的所有使用者!", _customerPageModel);
}
6 分頁測試組合
{
"pageIndex": 1,
"pageSize": 10,
"orderByModel": "",
"queryCondition": ""
}
{
"pageIndex": 1,
"pageSize": 10,
"orderByModel": "",
"queryCondition": "{\"Name\":\"張\"}"
}
{
"pageIndex": 1,
"pageSize": 10,
"orderByModel": "{\"OrderByFiled\":\"id\",\"OrderByType\":\"ascending\"}",
"queryCondition": "{\"Name\":\"張\",\"IsSystemAccount\":true}"
}
{
"pageIndex": 1,
"pageSize": 10,
"orderByModel": "{\"OrderByFiled\":\"id\",\"OrderByType\":\"ascending\"}",
"queryCondition": "{\"Name\":\"張\",\"IsSystemAccount\":true,\"IsActive\":true}"
}
{
"pageIndex": 1,
"pageSize": 10,
"orderByModel": "{\"OrderByFiled\":\"id\",\"OrderByType\":\"ascending\"}",
"queryCondition": "{\"Name\":\"張\",\"IsSystemAccount\":true,\"IsActive\":true,\"IsDeleted\":false}"
}
對以上功能更為具體實作和注釋見:230223_041shopDemo(所有使用者執行個體的分頁實作)。