zoukankan      html  css  js  c++  java
  • 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 构建智能查询 一、智能查询的需求与设计

  • 相关阅读:
    python遍历字典元素
    Asp.net网站优化【转】
    三、HTTP协议
    二、 OSI模型的实现TCP 、IP
    一、OSI模型
    JVM原理:4 运行期优化
    JS:jquery插件表格单元格合并.
    28-语言入门-28-1的个数
    27-语言入门-27-成绩转换
    26-语言入门-26-兄弟郊游问题
  • 原文地址:https://www.cnblogs.com/chsword/p/searchmodel_2.html
Copyright © 2011-2022 走看看