.net通用CMS快速开发框架——问题:Dapper通用的多表联合分页查询怎么破?

内容预览:
  • 最近在弄一个东东,类似那种CMS的后台管理系统,方便作为其它项目的初始...~
  • public class MvcApplication : System.Web.HttpApplication { protecte...~
  • //如需加载实现的程序集,将dll拷贝到bin目录下即可,不用引用dll var i...~

最近在弄一个东东,类似那种CMS的后台管理系统,方便作为其它项目的初始化框架用的。

现在遇到个问题,如标题所示:Dapper通用的多表联合分页查询怎么破?

单表的话很简单就可以实现,多表不通用的话也可以很方便的实现,那么如果多表通用的话,怎么办呢?

难道只能通过拼接sql或者使用存储过程吗?我先来展示下我的实现方式,希望你有更好的方式,然后同我分享一下,以便解决我的困扰。

技术选型:MVC5、Mysql、Dapper、Autofac、Layui、阿里巴巴矢量库、T4(后面补上)。

我选择的都是轻量级比较干净的东东来组合的框架。

我选择由外入内的方式来阐述我现在遇到的问题。以用户管理界面为例,我讲只列出涉及到用户分页查询的代码,将会省略其它代码…..

大致上的效果如下图所示:

经典的多层架构

Global.asax.cs代码,Dapper自动注入。

  public class MvcApplication : System.Web.HttpApplication

{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);

//创建autofac管理注册类的容器实例
var builder = new ContainerBuilder();
SetupResolveRules(builder);
//使用Autofac提供的RegisterControllers扩展方法来对程序集中所有的Controller一次性的完成注册 支持属性注入
builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();

// 把容器装入到微软默认的依赖注入容器中
var container = builder.Build();
DependencyResolver.SetResolver(
new AutofacDependencyResolver(container));
}
private static void SetupResolveRules(ContainerBuilder builder)
{
//WebAPI只用引用services和repository的接口,不用引用实现的dll。
//如需加载实现的程序集,将dll拷贝到bin目录下即可,不用引用dll
var iServices = Assembly.Load("RightControl.IService");
var services = Assembly.Load("RightControl.Service");
var iRepository = Assembly.Load("RightControl.IRepository");
var repository = Assembly.Load("RightControl.Repository");

//根据名称约定(服务层的接口和实现均以Services结尾),实现服务接口和服务实现的依赖
builder.RegisterAssemblyTypes(iServices, services)
.Where(t
=> t.Name.EndsWith("Service"))
.AsImplementedInterfaces().PropertiesAutowired();

//根据名称约定(数据访问层的接口和实现均以Repository结尾),实现数据访问接口和数据访问实现的依赖
builder.RegisterAssemblyTypes(iRepository, repository)
.Where(t
=> t.Name.EndsWith("Repository"))
.AsImplementedInterfaces().PropertiesAutowired();
}
}

BaseController:

   public class BaseController : Controller

{
// GET: Base
public virtual ActionResult Index()
{
return View();
}

UserController:

    public class UserController : BaseController

{
private IUserService service;

public UserController(IUserService _service)
{
service
= _service;
}
/// <summary>
/// 加载数据列表
/// </summary>
/// <param name="pageInfo">页面实体信息</param>
/// <param name="filter">查询条件</param>
/// <returns></returns>
[HttpGet]
public JsonResult List(PageInfo pageInfo, UserModel filter)
{
var result = service.GetListByFilter(filter, pageInfo);
return Json(result, JsonRequestBehavior.AllowGet);
}

PageInfo:


    public class PageInfo

{
public int page { get; set; }
public int limit { get; set; }
/// <summary>
/// 排序字段 CreateOn
/// </summary>
public string field { get; set; }
/// <summary>
/// 排序方式 asc desc
/// </summary>
public string order { get; set; }
/// <summary>
/// 返回字段逗号分隔
/// </summary>
public string returnFields { get; set; }
public string prefix { get; set; }
}

View Code

UserModel:


using DapperExtensions;

using System;
using System.ComponentModel.DataAnnotations;

namespace RightControl.Model
{
[Table(
"t_User")]
public class UserModel:Entity
{
/// <summary>
/// 用户名
/// </summary>
[Display(Name = "用户名")]
public string UserName { get; set; }
/// <summary>
/// 真实名称
/// </summary>
[Display(Name = "真实名称")]
public string RealName { get; set; }
/// <summary>
/// 密码
/// </summary>
public string PassWord { get; set; }
/// <summary>
/// 创建者
/// </summary>
public int CreateBy { get; set; }
/// <summary>
/// 角色ID
/// </summary>
public int RoleId { get; set; }
/// <summary>
/// 更新时间
/// </summary>
[Display(Name = "更新时间")]
public DateTime UpdateOn { get; set; }
[Computed]
public string RoleName { get; set; }
}
}

View Code

Entity:

    public class Entity

{
[DapperExtensions.Key(
true)]
public virtual int Id { get; set; }
/// <summary>
/// 创建时间
/// </summary>
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString
= "")]
[Display(Name
= "创建时间")]
public DateTime CreateOn { get; set; }
/// <summary>
/// 菜单状态(1:启用,0:禁用)
/// </summary>
public bool Status { get; set; }
#region 查询条件
[Computed]
public string StartEndDate { get; set; }
#endregion
}

IBaseService:

    public interface IBaseService<T> where T : class, new()

{
dynamic GetListByFilter(T filter, PageInfo pageInfo);
}

IUserService:

    public interface IUserService : IBaseService<UserModel>

{
...
}

BaseService:

    public abstract class BaseService<T> where T : class, new()

{
public IBaseRepository<T> baseRepository{get; set;}
public dynamic GetPageUnite(IBaseRepository<T> repository, PageInfo pageInfo, string where, object filter)
{
string _orderBy = string.Empty;
if (!string.IsNullOrEmpty(pageInfo.field))
{
_orderBy
= string.Format(" ORDER BY ", pageInfo.prefix+pageInfo.field, pageInfo.order);
}
else
{
_orderBy
= string.Format(" ORDER BY CreateOn desc",pageInfo.prefix);
}
long total = 0;
var list = repository.GetByPageUnite(new SearchFilter { pageIndex = pageInfo.page, pageSize = pageInfo.limit, returnFields = pageInfo.returnFields, param = filter, where = where, orderBy = _orderBy }, out total);

return Pager.Paging(list, total);
}
protected string CreateWhereStr(Entity filter, string _where)
{
if (!string.IsNullOrEmpty(filter.StartEndDate) && filter.StartEndDate != " ~ ")
{
var dts = filter.StartEndDate.Trim().Split('~');
var start = dts[0].Trim();
var end = dts[1].Trim();
if (!string.IsNullOrEmpty(start))
{
_where
+= string.Format(" and CreateOn>=''", start + " 00:00");
}
if (!string.IsNullOrEmpty(end))
{
_where
+= string.Format(" and CreateOn<=''", end + " 59:59");
}
}

return _where;
}
}

UserService:

    public class UserService: BaseService<UserModel>, IUserService

{
public IUserRepository repository { get; set; }//属性注入
public dynamic GetListByFilter(UserModel filter, PageInfo pageInfo)
{
pageInfo.prefix
= "u.";
string _where = " t_User u INNER JOIN t_role r on u.RoleId=r.Id";
if (!string.IsNullOrEmpty(filter.UserName))
{
_where
+= string.Format(" and [email protected]",pageInfo.prefix);
}
if (!string.IsNullOrEmpty(pageInfo.order))
{
pageInfo.order
= pageInfo.prefix + pageInfo.order;
}
pageInfo.returnFields
= string.Format("Id,UserName,RealName,CreateOn,`PassWord`,`Status`,RoleId,r.RoleName",pageInfo.prefix);
return GetPageUnite(baseRepository, pageInfo, _where, filter);
}

IBaseRepository:

 public interface IBaseRepository<T> where T : class, new()

{
IEnumerable
<T> GetByPageUnite(SearchFilter filter, out long total);
}

IUserRepository:

    public interface IUserRepository : IBaseRepository<UserModel>

{

}

BaseRepository:

    public class BaseRepository<T>: IBaseRepository<T> where T :class, new()

{
public IEnumerable<T> GetByPageUnite(SearchFilter filter, out long total)
{
using (var conn = MySqlHelper.GetConnection())
{
return conn.GetByPageUnite<T>(filter.pageIndex, filter.pageSize, out total, filter.returnFields, filter.where, filter.param, filter.orderBy, filter.transaction, filter.commandTimeout);
}
}

}

UserRepository:

    public class UserRepository : BaseRepository<UserModel>, IUserRepository

{

}

最后的分页代码:

        /// <summary>

/// 获取分页数据
/// </summary>
public static IEnumerable<T> GetByPageUnite<T>(this IDbConnection conn, int pageIndex, int pageSize, out long total, string returnFields = null, string where = null, object param = null,
string orderBy = null, IDbTransaction transaction = null, int? commandTimeout = null)
{
int skip = 0;
if (pageIndex > 0)
{
skip
= (pageIndex - 1) * pageSize;
}

StringBuilder sb
= new StringBuilder();
sb.AppendFormat(
"SELECT COUNT(1) FROM ;", where);
sb.AppendFormat(
"SELECT FROM LIMIT ,", returnFields, where, orderBy, skip, pageSize);
using (var reader = conn.QueryMultiple(sb.ToString(), param, transaction, commandTimeout))
{
total
= reader.ReadFirst<long>();
return reader.Read<T>();
}
}

Index视图:

@{

Layout = "~/Views/Shared/_LayoutBase.cshtml";
}

<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8">
<title>Table</title>
</head>

<body>
<div class="admin-main">
<blockquote class="layui-elem-quote p10">
<div class="layui-form-item" style="margin-bottom:0px;">
<label class="layui-form-label">用户名称:</label>
<div class="layui-input-inline">
<input name="UserName" id="UserName" lay-verify="url" autocomplete="off" class="layui-input">
</div>
<a href="javascript:;" class="layui-btn layui-btn-sm" id="btnSearch" data-type="reload">
<i class="layui-icon">&#xe615;</i> 搜索
</a>
<div style="float:right;">
<a href="javascript:;" class="layui-btn layui-btn-sm" id="btnAdd">
<i class="layui-icon">&#xe608;</i> 添加用户
</a>
</div>
</div>
</blockquote>
<div class="layui-field-box">
<table id="defaultTable" lay-filter="defaultruv"></table>
<script type="text/html" id="switchTpl">
{{#
if(d.Status == 1){ }}
<i class="layui-icon green">&#xe618;</i>启用
{{# } else { }}
<i class="layui-icon red" style="font-size:18px;">&#x1006;</i> 停用
{{# } }}
<!-- 这里的 checked 的状态只是演示 -->
@
*<input type="checkbox" name="Status" value="{}" lay-skin="switch" lay-text="开启|禁用" lay-filter="statusSwitch" {{ d.Status == 1 ? 'checked' : '' }}>*@
</script>
<script type="text/html" id="bar">
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="detail">查看</a>
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
</script>
</div>
</div>
<script>
layui.config({
base:
'/plugins/app/'
});

layui.use([
'table', 'common', 'form'], function () {
var table = layui.table,
form
= layui.form,
common
= layui.common;
//表格
table.render({
id:
'defaultReload'
, elem:
'#defaultTable'
, height:
'full-112' //高度最大化减去差值
, url: '/Permissions/User/List' //数据接口
, page: true //开启分页
, cols: [[ //表头
{ checkbox: true, fixed: true },
{ field:
'Id', title: 'Id', width: 80, fixed: 'left' }
, { field:
'UserName', title: '用户名称', sort: true }
, { field:
'RealName', title: '真实姓名' }
, { field:
'RoleName', title: '角色名称' }
, { field:
'Status', title: '状态', templet: '#switchTpl', unresize: true, width: 100, align:'center' }
, { field:
'CreateOn', title: '创建时间', sort: true, templet: '<div>{}</div>' }
, { field:
'', title: '操作', toolbar: "#bar" }
]]
});
var $ = layui.$, active = {
reload:
function () {
//执行重载
table.reload('defaultReload', {
page: {
curr:
1 //重新从第 1 页开始
}
, where: {
UserName: $(
"#UserName").val()
}
});
}
};
$(
'#btnSearch').on('click', function () {
var type = $(this).data('type');
active[type]
? active[type].call(this) : '';
});
//add
$('#btnAdd').on('click', function () {
common.openTop({
title:
'用户编辑', w: '600px', h: '360px', content: '/Permissions/User/Add/', clickOK: function (index, layero) {
var form = layero.find('iframe')[0].contentDocument.forms[0];
ajaxSubmitForm($(form),
function (data) {
if (data.state == "success") {
common.msgSuccess(
"添加成功");
layer.close(index);
//关闭弹窗
active.reload();//刷新界面
}
});
}
});
});
//监听工具条
table.on('tool(defaultruv)', function (obj) {
var data = obj.data;
if (obj.event === 'detail') {
common.openTop({
detail:
true,
title:
'用户详情', w: '600px', h: '360px', content: '/Permissions/User/Detail/' + data.Id, clickOK: function (index) {
common.close(index);
}
});
}
else if (obj.event === 'del') {
layer.confirm(
'确定要删除吗?', function (index) {
console.log(data);
$.ajax({
url:
"/Permissions/User/Delete",
type:
"POST",
data: {
"Id": data.Id },
dataType:
"json",
success:
function (data) {
if (data.state == "success") {
//删除这一行
obj.del();
//关闭弹框
layer.close(index);
common.msgSuccess(
"删除成功");
}
else {
common.msgError(
"删除失败");
}
}
});
});
}
else if (obj.event === 'edit') {
common.openTop({
title:
'用户编辑', w: '600px', h: '360px', content: '/Permissions/User/Edit/' + data.Id, clickOK: function (index,layero) {
var form = layero.find('iframe')[0].contentDocument.forms[0];
ajaxSubmitForm($(form),
function (data) {
if (data.state == "success") {
common.msgSuccess(
"修改成功");
layer.close(index);
//关闭弹窗
active.reload();//刷新界面
}
});
}
});
}
});
});
</script>
</body>

</html>

_LayoutBase模板页:

<!DOCTYPE html>


<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
<link rel="stylesheet" href="~/plugins/layui/css/layui.css" media="all" />
<link href="~/Content/global.css" rel="stylesheet" />
<link href="~/Content/table.css" rel="stylesheet" />
<script src="~/plugins/layui/layui.js"></script>
<script src="~/plugins/app/global.js"></script>
</head>
<body>
<div id="ajax-loader" style="cursor: progress; position: fixed; top: -50%; left: -50%; width: 200%; height: 200%; background: #fff; z-index: 10000; overflow: hidden;">
<img src="~/Content/images/ajax-loader.gif" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; margin: auto;" />
</div>
@RenderBody()
<script type="text/javascript">
layui.config({
base:
'/plugins/app/',
version:
'1522709297490' //为了更新 js 缓存,可忽略
});
layui.use([
'common'], function () {
layer.config({
skin:
'layui-layer-molv'
})
var $ = layui.jquery;
$(
function () {
$(
'#ajax-loader').fadeOut();
})
})
</script>
</body>
</html>

代码结构基本上就这样了,如果大家能把困扰我的这问题解决了,我就可以安安心心的把代码开源啦!

作为一名有追求的程序员,当看到代码连自己都受不了,我就开始抓狂,每次写代码的时候,脑袋里都是那几句话“不要重复你的代码、依赖于抽象….”

以上就是:.net通用CMS快速开发框架——问题:Dapper通用的多表联合分页查询怎么破? 的全部内容。

本站部分内容来源于互联网和用户投稿,如有侵权请联系我们删除,谢谢。
Email:[email protected]


0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论