ASP.NET MVC & EF 构建智能查询 二、模型的设计与ModelBinder

简介: 在第一篇中,我讲解了我们要做智能查询的原因,以及基本的解决方案设计。从这篇开始我们开始讲解它的实现过程。 其实在写这一系列文章之初,我其实是想由底至上去讲解,但是我又整理了一遍代码才发现,其实如果不了解最表面的东西,也是不太好深入的。

在第一篇中,我讲解了我们要做智能查询的原因,以及基本的解决方案设计。从这篇开始我们开始讲解它的实现过程。

其实在写这一系列文章之初,我其实是想由底至上去讲解,但是我又整理了一遍代码才发现,其实如果不了解最表面的东西,也是不太好深入的。

所以我们的第二篇文章就来讲一下我们这个智能查询框架中最浅,但也是使用最频繁的部分,也就是Model。

首先我们的Entity  或者说数据库的结构如下

image

另外如下面代码,我们有一个用于传递name=value对,及查询谓词的model

   1: public ActionResult Index(QueryModel model)
   2: {
   3:     using(var db=new DbEntities())
   4:     {
   5:         var list = db.Users.Where(model).ToList();
   6:         return View(list);
   7:     }
   8: }

我命名之为QueryModel。它由Action的参数传入,再传入EF的Where扩展方法,它是构建Lambda表达式的原型,上面是我们的一个通用的查询Action的代码。

 

而QueryModel的代码为

image

QueryModel的唯一一个属性Items,是一个ConditionItem的集合,它里面存着所有的查询条件。

而ConditionItem里面的属性

  1. Field表示要查询的目标属性的名称,我们的设定它是支持子属性查询的,例如 “Profile.MyUser.Id”
  2. Method则是当前使用的谓词,它是QueryMethod的一个枚举值
  3. OrGroup是一个字符串,是一个OrGroup的多个表达式将会以Or操作符进行关联,然后再And
  4. Prefix是一个分类的前缀,我们假定一个Action可能处理多个查询条件组的时候为了分开这些查询条件而加的属性
  5. Value则是这个表达试的值

 

而我们在页面上类似

   1: <form action="" method="post">
   2: 姓名:<input id="Name" name="[Like]Name" type="text" value="" />   
   3: Email:<input id="Email" name="[Equal]Email" type="text" value="" /><br />
   4: Id: <input id="Id" name="[Equal]Id" type="text" value="" />
   5: 生日: <input id="Birthday" name="[Equal]Birthday" type="text" value="" /><br />
   6: <input type="submit" value="查询" />
   7: </form>

这样的表单,我们提交到服务器端,我们要进行ASP.NET MVC 中IModelBinder的转换,要将querystring 或 postdata中的KeyValuePair转换为我们的ConditionItem。

当然,我们除了谓词Method之外,还有Prefix以及OrGroup要从客户端提交过来所以我们就要制定一个规则

我们约定

  1. 中括号[]中的为查询谓词
  2. 小括号()中的为前缀Prefix
  3. 大括号{}中的为OrGroup

我们可以通过以下IModelBinder的实现将Request.QueryString或Request.Form中的值转换到QueryModel中:

   1: public class SearchModelBinder : IModelBinder
   2:    {
   3:        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
   4:        {
   5:            var model = (QueryModel)(bindingContext.Model ?? new QueryModel());
   6:            var dict = controllerContext.HttpContext.Request.Params;
   7:            var keys = dict.AllKeys.Where(c => c.StartsWith("["));//我们认为只有[开头的为需要处理的
   8:            if (keys.Count() != 0)
   9:            {
  10:                foreach (var key in keys)
  11:                {
  12:                    if (!key.StartsWith("[")) continue;
  13:                    var val = dict[key];
  14:                    //处理无值的情况
  15:                    if (string.IsNullOrEmpty(val)) continue;
  16:                    AddSearchItem(model, key, val);
  17:                }
  18:            }
  19:            return model; 
  20:        }
  21:  
  22:        /// <summary>
  23:        /// 将一组key=value添加入QueryModel.Items
  24:        /// </summary>
  25:        /// <param name="model">QueryModel</param>
  26:        /// <param name="key">当前项的HtmlName</param>
  27:        /// <param name="val">当前项的值</param>
  28:        public static void AddSearchItem(QueryModel model, string key, string val)
  29:        {
  30:            string field = "", prefix = "", orGroup = "", method = "";
  31:            var keywords = key.Split(']', ')', '}');
  32:            //将Html中的name分割为我们想要的几个部分
  33:            foreach (var keyword in keywords)
  34:            {
  35:                if (Char.IsLetterOrDigit(keyword[0])) field = keyword;
  36:                var last = keyword.Substring(1);
  37:                if (keyword[0] == '(') prefix = last;
  38:                if (keyword[0] == '[') method = last;
  39:                if (keyword[0] == '{') orGroup = last;       
  40:            }
  41:            if (string.IsNullOrEmpty(method)) return;
  42:            if (!string.IsNullOrEmpty(field))
  43:            {
  44:                var item = new ConditionItem
  45:                               {
  46:                                   Field = field,
  47:                                   Value = val.Trim(),
  48:                                   Prefix = prefix,
  49:                                   OrGroup = orGroup,
  50:                                   Method = (QueryMethod) Enum.Parse(typeof (QueryMethod), method)
  51:                               };
  52:                model.Items.Add(item);
  53:            }
  54:        }
  55:    }

 

当然我们还要在Global.asax中添加

   1: ModelBinders.Binders.Add(typeof (QueryModel), new SearchModelBinder());

这样我们就可以在Action中获取到相应的查询条件了

image

我们可以看到,从表单提交过来的数据我们已经正确地存放在QueryModel中了。

 

ASP.NET MVC & EF 构建智能查询 一、智能查询的需求与设计

目录
打赏
0
0
0
0
1
分享
相关文章
一款基于 .NET + Blazor 开发的智能访客管理系统
一款基于 .NET + Blazor 开发的智能访客管理系统
深入理解MVC设计模式:构建高效Web应用程序的基石
【7月更文挑战第4天】在软件工程领域,设计模式是解决常见问题的一系列经过验证的方法。其中,Model-View-Controller(MVC)设计模式自诞生以来,便成为了构建用户界面,特别是Web应用程序的黄金标准。MVC通过将应用程序逻辑分离为三个核心组件,提高了代码的可维护性、可扩展性和重用性。本文将深入探讨MVC设计模式的原理,并通过一个简单的代码示例展示其应用。
269 0
Java一分钟之Spring MVC:构建Web应用
【5月更文挑战第15天】Spring MVC是Spring框架的Web应用模块,基于MVC模式实现业务、数据和UI解耦。常见问题包括:配置DispatcherServlet、Controller映射错误、视图解析未设置、Model数据传递遗漏、异常处理未配置、依赖注入缺失和忽视单元测试。解决这些问题可提升代码质量和应用性能。注意配置`web.xml`、`@RequestMapping`、`ViewResolver`、`Model`、`@ExceptionHandler`、`@Autowired`,并编写测试用例。
357 3
技术进阶:使用Spring MVC构建适应未来的响应式Web应用
【9月更文挑战第2天】随着移动设备的普及,响应式设计至关重要。Spring MVC作为强大的Java Web框架,助力开发者创建适应多屏的应用。本文推荐使用Thymeleaf整合视图,通过简洁的HTML代码提高前端灵活性;采用`@ResponseBody`与`Callable`实现异步处理,优化应用响应速度;运用`@ControllerAdvice`统一异常管理,保持代码整洁;借助Jackson简化JSON处理;利用Spring Security增强安全性;并强调测试的重要性。遵循这些实践,将大幅提升开发效率和应用质量。
94 7
闲话 Asp.Net Core 数据校验(三)EF Core 集成 FluentValidation 校验数据例子
闲话 Asp.Net Core 数据校验(三)EF Core 集成 FluentValidation 校验数据例子
122 1
利用查询条件对象,在Asp.net Web API中实现对业务数据的分页查询处理
利用查询条件对象,在Asp.net Web API中实现对业务数据的分页查询处理
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
87 0
ASP.NET Web Api 使用 EF 6,DateTime 字段如何取数据库服务器当前时间
ASP.NET Web Api 使用 EF 6,DateTime 字段如何取数据库服务器当前时间
(20)ASP.NET Core EF创建模型(必需属性和可选属性、最大长度、并发标记、阴影属性)
(20)ASP.NET Core EF创建模型(必需属性和可选属性、最大长度、并发标记、阴影属性)

热门文章

最新文章