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 构建智能查询 一、智能查询的需求与设计

  • 相关阅读:
    堆栈学习
    需要阅读的书籍
    Rust Book Lang Ch.19 Fully Qualified Syntax, Supertraits, Newtype Pattern, type aliases, never type, dynamic sized type
    Rust Lang Book Ch.19 Placeholder type, Default generic type parameter, operator overloading
    Rust Lang Book Ch.19 Unsafe
    Rust Lang Book Ch.18 Patterns and Matching
    Rust Lang Book Ch.17 OOP
    Rust Lang Book Ch.16 Concurrency
    Rust Lang Book Ch.15 Smart Pointers
    HDU3966-Aragorn's Story-树链剖分-点权
  • 原文地址:https://www.cnblogs.com/chsword/p/searchmodel_2.html
Copyright © 2011-2022 走看看