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 }
    复制代码

    备注

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

    ★快速评价★不错,支持一下! 
    ★快速评价★垃圾,还需努力!
     
  • 相关阅读:
    Visual C# 插件构架实战
    用CSS实现表格单元格数据自动换行或不换行
    页面代码开发规范:CSS命名规范(参考)
    UML之业务建模
    在.NET环境下将报表导出Excel和Word(网络转载)
    asp.net数据导出到Excel (从网络摘操)
    ASP.NET(VB)把数据导出到EXCEL的一种方法(网上转载)
    关于ASP,ASP.NET,VB.NET里的MD5加密函数(转载)
    .net打包自动安装数据库(转载)
    Cannot load required extension: curl
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3094893.html
Copyright © 2011-2022 走看看