一起谈.NET技术,ASP.NET MVC & EF 构建智能查询 二、模型的设计与ModelBinder

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

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

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

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

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

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

 
 
public ActionResult Index(QueryModel model)
{
using (var db = new DbEntities())
{
var list
= db.Users.Where(model).ToList();
return View(list);
}
}

  我命名之为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则是这个表达试的值。

  而我们在页面上类似:

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

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

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

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

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

 
   
public class SearchModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var model
= (QueryModel)(bindingContext.Model ?? new QueryModel());
var dict
= controllerContext.HttpContext.Request.Params;
var keys
= dict.AllKeys.Where(c => c.StartsWith( " [ " )); // 我们认为只有[开头的为需要处理的
if (keys.Count() != 0 )
{
foreach (var key in keys)
{
if ( ! key.StartsWith( " [ " )) continue ;
var val
= dict[key];
// 处理无值的情况
if ( string .IsNullOrEmpty(val)) continue ;
AddSearchItem(model, key, val);
}
}
return model;
}

/// <summary>
/// 将一组key=value添加入QueryModel.Items
/// </summary>
/// <param name="model"> QueryModel </param>
/// <param name="key"> 当前项的HtmlName </param>
/// <param name="val"> 当前项的值 </param>
public static void AddSearchItem(QueryModel model, string key, string val)
{
string field = "" , prefix = "" , orGroup = "" , method = "" ;
var keywords
= key.Split( ' ] ' , ' ) ' , ' } ' );
// 将Html中的name分割为我们想要的几个部分
foreach (var keyword in keywords)
{
if (Char.IsLetterOrDigit(keyword[ 0 ])) field = keyword;
var last
= keyword.Substring( 1 );
if (keyword[ 0 ] == ' ( ' ) prefix = last;
if (keyword[ 0 ] == ' [ ' ) method = last;
if (keyword[ 0 ] == ' { ' ) orGroup = last;
}
if ( string .IsNullOrEmpty(method)) return ;
if ( ! string .IsNullOrEmpty(field))
{
var item
= new ConditionItem
{
Field
= field,
Value
= val.Trim(),
Prefix
= prefix,
OrGroup
= orGroup,
Method
= (QueryMethod) Enum.Parse( typeof (QueryMethod), method)
};
model.Items.Add(item);
}
}
}

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

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

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

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

目录
相关文章
|
29天前
|
存储 Shell Linux
快速上手基于 BaGet 的脚本自动化构建 .net 应用打包
本文介绍了如何使用脚本自动化构建 `.net` 应用的 `nuget` 包并推送到指定服务仓库。首先概述了 `BaGet`——一个开源、轻量级且高性能的 `NuGet` 服务器,支持多种存储后端及配置选项。接着详细描述了 `BaGet` 的安装、配置及使用方法,并提供了 `PowerShell` 和 `Bash` 脚本实例,用于自动化推送 `.nupkg` 文件。最后总结了 `BaGet` 的优势及其在实际部署中的便捷性。
60 10
|
1月前
|
前端开发 安全 Java
技术进阶:使用Spring MVC构建适应未来的响应式Web应用
【9月更文挑战第2天】随着移动设备的普及,响应式设计至关重要。Spring MVC作为强大的Java Web框架,助力开发者创建适应多屏的应用。本文推荐使用Thymeleaf整合视图,通过简洁的HTML代码提高前端灵活性;采用`@ResponseBody`与`Callable`实现异步处理,优化应用响应速度;运用`@ControllerAdvice`统一异常管理,保持代码整洁;借助Jackson简化JSON处理;利用Spring Security增强安全性;并强调测试的重要性。遵循这些实践,将大幅提升开发效率和应用质量。
54 7
|
2月前
|
设计模式 存储 前端开发
揭秘.NET架构设计模式:如何构建坚不可摧的系统?掌握这些,让你的项目无懈可击!
【8月更文挑战第28天】在软件开发中,设计模式是解决常见问题的经典方案,助力构建可维护、可扩展的系统。本文探讨了.NET中三种关键架构设计模式:MVC、依赖注入与仓储模式,并提供了示例代码。MVC通过模型、视图和控制器分离关注点;依赖注入则通过外部管理组件依赖提升复用性和可测性;仓储模式则统一数据访问接口,分离数据逻辑与业务逻辑。掌握这些模式有助于开发者优化系统架构,提升软件质量。
41 5
|
2月前
|
机器学习/深度学习 人工智能 算法
【悬念揭秘】ML.NET:那片未被探索的机器学习宝藏,如何让普通开发者一夜变身AI高手?——从零开始,揭秘构建智能应用的神秘旅程!
【8月更文挑战第28天】ML.NET 是微软推出的一款开源机器学习框架,专为希望在本地应用中嵌入智能功能的 .NET 开发者设计。无需深厚的数据科学背景,即可实现预测分析、推荐系统和图像识别等功能。它支持多种数据源,提供丰富的预处理工具和多样化的机器学习算法,简化了数据处理和模型训练流程。
37 1
|
2月前
|
存储 缓存 安全
.NET 在金融行业的应用:高并发交易系统的构建与优化之路
【8月更文挑战第28天】在金融行业,交易系统需具备高并发处理、低延迟及高稳定性和安全性。利用.NET构建此类系统时,可采用异步编程提升并发能力,优化数据库访问以降低延迟,使用缓存减少数据库访问频率,借助分布式事务确保数据一致性,并加强安全性措施。通过综合优化,满足金融行业的严苛要求。
34 1
|
2月前
|
大数据 开发工具 开发者
从零到英雄:.NET核心技术带你踏上编程之旅,构建首个应用,开启你的数字世界探险!
【8月更文挑战第28天】本文带领读者从零开始,使用强大的.NET平台搭建首个控制台应用。无论你是新手还是希望扩展技能的开发者,都能通过本文逐步掌握.NET的核心技术。从环境搭建到创建项目,再到编写和运行代码,详细步骤助你轻松上手。通过计算两数之和的小项目,你不仅能快速入门,还能为未来开发更复杂的应用奠定基础。希望本文为你的.NET学习之旅开启新篇章!
29 1
|
2月前
|
缓存 运维 前端开发
阿里云云效操作报错合集之如何解决在使用流水线构建net8应用时遇到无法构建的报错
本合集将整理呈现用户在使用过程中遇到的报错及其对应的解决办法,包括但不限于账户权限设置错误、项目配置不正确、代码提交冲突、构建任务执行失败、测试环境异常、需求流转阻塞等问题。阿里云云效是一站式企业级研发协同和DevOps平台,为企业提供从需求规划、开发、测试、发布到运维、运营的全流程端到端服务和工具支撑,致力于提升企业的研发效能和创新能力。
|
2月前
|
C# Windows 开发者
超越选择焦虑:深入解析WinForms、WPF与UWP——谁才是打造顶级.NET桌面应用的终极利器?从开发效率到视觉享受,全面解读三大框架优劣,助你精准匹配项目需求,构建完美桌面应用生态系统
【8月更文挑战第31天】.NET框架为开发者提供了多种桌面应用开发选项,包括WinForms、WPF和UWP。WinForms简单易用,适合快速开发基本应用;WPF提供强大的UI设计工具和丰富的视觉体验,支持XAML,易于实现复杂布局;UWP专为Windows 10设计,支持多设备,充分利用现代硬件特性。本文通过示例代码详细介绍这三种框架的特点,帮助读者根据项目需求做出明智选择。以下是各框架的简单示例代码,便于理解其基本用法。
73 0
|
2月前
|
Java Spring 自然语言处理
Spring 框架里竟藏着神秘魔法?国际化与本地化的奇妙之旅等你来揭开谜底!
【8月更文挑战第31天】在软件开发中,国际化(I18N)与本地化(L10N)对于满足不同地区用户需求至关重要。Spring框架提供了强大支持,利用资源文件和`MessageSource`实现多语言文本管理。通过配置日期格式和货币符号,进一步完善本地化功能。合理应用这些特性,可显著提升应用的多地区适应性和用户体验。
32 0
|
2月前
|
传感器 开发框架 物联网
揭开.NET在IoT领域的神秘面纱:如何构建智能设备,让未来生活触手可及?
【8月更文挑战第28天】随着物联网技术的发展,智能设备正深入我们的生活。.NET作为跨平台开源框架,在IoT领域应用广泛。本文介绍如何利用.NET构建智能设备,通过实例展示从环境搭建到项目创建、代码编写及运行的全过程,帮助开发者快速实现IoT解决方案,开启智能设备开发的新篇章。
33 0
下一篇
无影云桌面