您的位置:首页 > 运维架构 > 网站架构

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

2013-05-23 08:57 267 查看

背景

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

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

什么是CQRS

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

简单的CQRS



复杂的CQRS



CQRS的常见查询需求

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

查询面板



高级查询



数据行级别的权限

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

固定约束

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

需求总结



CQRS的查询设计

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

关键决策:

直接查询数据库返回Dynamic类型,不需要定义强类型。

直接用SQL,支持动态查询面板和动态数据行权限。目前没有找到封装SQL的理由,最多是在外围再封装一层,但是不会隐藏SQL(我之前写过一个简单的查询对象)。

利用一些策略防止SQL注入和权限提升(这篇文章不介绍)。

示例代码

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

AJAX程序

/// <reference path="Ext/ext-all-debug-w-comments.js" />

Ext.onReady(function () {
var query = {
TableOrViewName: 'Users',
WhereClause: "Name NOT LIKE '%段%'"
};

Ext.Ajax.request({
url: 'TestDynamicQuery/Fetch',
method: 'POST',
params: { query: Ext.encode(query) },
success: function (response) {
console.log(response.responseText);
}
});

query = {
TableOrViewName: 'Users',
WhereClause: "Age >= 20 AND Age <= 27"
};

Ext.Ajax.request({
url: 'TestDynamicQuery/Fetch',
method: 'POST',
params: { query: Ext.encode(query) },
success: function (response) {
console.log(response.responseText);
}
});
});


万能查询控制器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;

using Newtonsoft.Json;

using Happy.Query;

namespace Happy.Web.Mvc
{
/// <summary>
/// 动态查询控制器。
/// </summary>
public abstract class DynamicQueryController<TDynamicQueryService> : AjaxController
where TDynamicQueryService : IDynamicQueryService
{
/// <summary>
/// 动态查询服务。
/// </summary>
protected abstract TDynamicQueryService QueryService { get; }

/// <summary>
/// 获取分页数据,面向表格。
/// </summary>
public ActionResult Page(DynamicQueryObject query)
{
var result = this.QueryService.Page(query);

return this.Json(result);
}

/// <summary>
/// 获取列表数据,面向不需要分页的表格或下拉框。
/// </summary>
public ActionResult Fetch(DynamicQueryObject query)
{
var result = this.QueryService.Fetch(query);

return this.NewtonsoftJson(result);
}

/// <summary>
/// 获取一个数据,面向表单。
/// </summary>
public ActionResult SingleOrDefault(DynamicQueryObject query)
{
var result = this.QueryService.Fetch(query);

return this.NewtonsoftJson(result);
}
}
}


万能查询对象

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Happy.Query
{
/// <summary>
/// 动态查询对象。
/// </summary>
public sealed class DynamicQueryObject
{
/// <inheritdoc />
public DynamicQueryObject()
{
this.Columns = new List<string>();
this.Page = 1;
this.ItemsPerPage = 25;
}

/// <summary>
/// 表或试图名字。
/// </summary>
public string TableOrViewName { get; set; }

/// <summary>
/// 表或试图名字。
/// </summary>
public List<string> Columns { get; set; }

/// <summary>
/// Where子句。
/// </summary>
public string WhereClause { get; set; }

/// <summary>
/// Order子句。
/// </summary>
public string OrderClause { get; set; }

/// <summary>
/// 第几页数据。
/// </summary>
public long Page { get; set; }

/// <summary>
/// 每页条数。
/// </summary>
public long ItemsPerPage { get; set; }
}
}


备注

写这篇文章的目的,是系统大家多给些意见,我想知道你们是如何应对这种查询需求的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: