zoukankan      html  css  js  c++  java
  • CQRS:CQRS+AJAX架构 之 查询(Q)模型设计

    CQRS:CQRS+AJAX架构 之 查询(Q)模型设计

    背景

    准备采用CQRS架构,之前也简单的应用过(只是把读和写在程序级别进行了分离),这篇文章是我最近几天的思考,写下来希望大家多提意见。这篇文章不会涉及Command端的设计,重点关注如何设计查询。

    真心的希望大家看完后能给出你们的意见和想法。

    什么是CQRS

    CQRS:Command Query Responsibility Separation。我喜欢职责分离,这也是我采用这种架构的原因,确实能带来单一职责的优点。

    简单的CQRS

    复杂的CQRS

    CQRS的常见查询需求

    下面是系统的一些查询需求:

    查询面板

    高级查询

    数据行级别的权限

    如:个人、部门、分公司、品种。

    固定约束

    如:启用、合法、租户ID。

    需求总结

    CQRS的查询设计

    充分利用SQL和动态类型的优势,不做太多无谓的封装。

    关键决策:

      1. 直接查询数据库返回Dynamic类型,不需要定义强类型。
      2. 直接用SQL,支持动态查询面板和动态数据行权限。目前没有找到封装SQL的理由,最多是在外围再封装一层,但是不会隐藏SQL(我之前写过一个简单的查询对象)。
      3. 利用一些策略防止SQL注入和权限提升(这篇文章不介绍)。

    示例代码

    下载地址:http://happy.codeplex.com/SourceControl/latest

    AJAX程序

    复制代码
     1 /// <reference path="Ext/ext-all-debug-w-comments.js" />
     2 
     3 Ext.onReady(function () {
     4     var query = {
     5         TableOrViewName: 'Users',
     6         WhereClause: "Name NOT LIKE '%段%'"
     7     };
     8 
     9     Ext.Ajax.request({
    10         url: 'TestDynamicQuery/Fetch',
    11         method: 'POST',
    12         params: { query: Ext.encode(query) },
    13         success: function (response) {
    14             console.log(response.responseText);
    15         }
    16     });
    17 
    18     query = {
    19         TableOrViewName: 'Users',
    20         WhereClause: "Age >= 20 AND Age <= 27"
    21     };
    22 
    23     Ext.Ajax.request({
    24         url: 'TestDynamicQuery/Fetch',
    25         method: 'POST',
    26         params: { query: Ext.encode(query) },
    27         success: function (response) {
    28             console.log(response.responseText);
    29         }
    30     });
    31 });
    复制代码

    万能查询控制器

    复制代码
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 using System.Web.Mvc;
     7 
     8 using Newtonsoft.Json;
     9 
    10 using Happy.Query;
    11 
    12 namespace Happy.Web.Mvc
    13 {
    14     /// <summary>
    15     /// 动态查询控制器。
    16     /// </summary>
    17     public abstract class DynamicQueryController<TDynamicQueryService> : AjaxController
    18         where TDynamicQueryService : IDynamicQueryService
    19     {
    20         /// <summary>
    21         /// 动态查询服务。
    22         /// </summary>
    23         protected abstract TDynamicQueryService QueryService { get; }
    24 
    25         /// <summary>
    26         /// 获取分页数据,面向表格。
    27         /// </summary>
    28         public ActionResult Page(DynamicQueryObject query)
    29         {
    30             var result = this.QueryService.Page(query);
    31 
    32             return this.Json(result);
    33         }
    34 
    35         /// <summary>
    36         /// 获取列表数据,面向不需要分页的表格或下拉框。
    37         /// </summary>
    38         public ActionResult Fetch(DynamicQueryObject query)
    39         {
    40             var result = this.QueryService.Fetch(query);
    41 
    42             return this.NewtonsoftJson(result);
    43         }
    44 
    45         /// <summary>
    46         /// 获取一个数据,面向表单。
    47         /// </summary>
    48         public ActionResult SingleOrDefault(DynamicQueryObject query)
    49         {
    50             var result = this.QueryService.Fetch(query);
    51 
    52             return this.NewtonsoftJson(result);
    53         }
    54     }
    55 }
    复制代码

    万能查询对象

    复制代码
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 
     7 namespace Happy.Query
     8 {
     9     /// <summary>
    10     /// 动态查询对象。
    11     /// </summary>
    12     public sealed class DynamicQueryObject
    13     {
    14         /// <inheritdoc />
    15         public DynamicQueryObject()
    16         {
    17             this.Columns = new List<string>();
    18             this.Page = 1;
    19             this.ItemsPerPage = 25;
    20         }
    21 
    22         /// <summary>
    23         /// 表或试图名字。
    24         /// </summary>
    25         public string TableOrViewName { get; set; }
    26 
    27         /// <summary>
    28         /// 表或试图名字。
    29         /// </summary>
    30         public List<string> Columns { get; set; }
    31 
    32         /// <summary>
    33         /// Where子句。
    34         /// </summary>
    35         public string WhereClause { get; set; }
    36 
    37         /// <summary>
    38         /// Order子句。
    39         /// </summary>
    40         public string OrderClause { get; set; }
    41 
    42         /// <summary>
    43         /// 第几页数据。
    44         /// </summary>
    45         public long Page { get; set; }
    46 
    47         /// <summary>
    48         /// 每页条数。
    49         /// </summary>
    50         public long ItemsPerPage { get; set; }
    51     }
    52 }
    复制代码

    备注

    写这篇文章的目的,是系统大家多给些意见,我想知道你们是如何应对这种查询需求的。

    ★快速评价★不错,支持一下! 
    ★快速评价★垃圾,还需努力!
     
  • 相关阅读:
    Leetcode Excel Sheet Column Number
    AlgorithmsI PA2: Randomized Queues and Deques Subset
    AlgorithmsI PA2: Randomized Queues and Deques RandomizedQueue
    AlgorithmsI PA2: Randomized Queues and Deques Deque
    AlgorithmsI Programming Assignment 1: PercolationStats.java
    hdu多校第四场 1003 (hdu6616) Divide the Stones 机智题
    hdu多校第四场 1007 (hdu6620) Just an Old Puzzle 逆序对
    hdu多校第四场1001 (hdu6614) AND Minimum Spanning Tree 签到
    hdu多校第三场 1007 (hdu6609) Find the answer 线段树
    hdu多校第三场 1006 (hdu6608) Fansblog Miller-Rabin素性检测
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3094893.html
Copyright © 2011-2022 走看看