连载:(二)循序渐进,通过XML配置,实现通用于WinForm(.Net)、WebForm(Asp.Net+JQuery+EasyUI)表单、报表
--原理
作者:长江支流
本原理,适用于Window Form的CS,也适用于ASP.Net的BS。
在描述原理之前,先来看个传统的ORM写代码的例子。
实体映射
现在很多架构实现ORM,去动态的生成代码,实现数据增、删、改、查的功能。
实体的映射关系,是通过代码的方式进行映射的,是否可以通过XML文件,来配置实例的映射关系,答案是肯定的。
代码映射
这里,先看一下主键为ID的表test_EntityAccessORM有两个字段DM、MC表示代码、名称,表字段与实体的映射代码实现方式。
(注意:写代码不是我们本意,我们将要抛弃代码,程序员就是为了不写代码或少写代码!)
using System; using WebMIS.Data.EntityAccess; using WebMIS.Data.EntityAccess.MapAttribute; namespace WebMIS.Data.EntityAccess.Test { /// <summary> /// 实体映射。 /// </summary> //描述映射的表名,主键(主键可多个),如("myTable","ID,NO")或("myTable","ID","NO"),可写在类申明上,也可写在无参公有构造函数上,且类上优先。 [WebMIS.Data.EntityAccess.MapAttribute.TableMap("test_EntityAccessORM","ID")] public class EntityMapByAuto:WebMIS.Data.EntityAccess.EntityAutoMap { private long _ID; //ID private string _Code ; //代码 private string _Name ; //名称 //[WebMIS.Data.EntityAccess.MapAttribute.TableMap("test_EntityAccessORM","ID")] public EntityMapByAuto() { } [WebMIS.Data.EntityAccess.MapAttribute.ColumnMap("ID",System.Data.DbType.UInt32)] public long ID { get{return _ID;} set{_ID = value;} } [WebMIS.Data.EntityAccess.MapAttribute.ColumnMap("dm")] public string Code { get{return _Code;} set{_Code = value;} } [WebMIS.Data.EntityAccess.MapAttribute.ColumnMap("mc")] public string Name { get{return _Name;} set{_Name = value;} } //以下公有字段或属性,没有ColumnMap ,不参预ORM public string abc=""; public static string ABCD { get{return "ABCD1";} } } }
由此可知,通过属性类WebMIS.Data.EntityAccess.MapAttribute.TableMap指定表及主键,通过WebMIS.Data.EntityAccess.MapAttribute.ColumnMap指定数据库表字段与属性的对应映射关系。大家从VS自带的实体框架EF中也可以找出类似的实现原理。
XML映射
我们这里要实现的,是通过XML配置文件,配置表字段与实体的映射关系,不写代码的实现方式。这样的好处时,只需要改配置文件,无需编译再发布部署程序,灵活方便。
这里,特别要注意的是,XML<Field>节点中<lD>表示WinForm/WebForm中控件的ID属性或标准html元素的name属性,<Name>表示Select中指定的字段名。
而且还要注意:<Field>定义,<lD>要与UI中控件或元素ID/Name属性相同(区分大小写)、<Name>是<Select>元素中写出的字段,区分大小写。
<?xml version="1.0" encoding="utf-8"?> <WebMisControllerSerializer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Controller> <!--注意,Select中的字段大小写,所以Field中的Name节点,要与之一样--> <Select>Select ID, DM,MC From test_EntityAccessORM</Select> <TableName>test_EntityAccessORM</TableName> <PrimaryKey>ID</PrimaryKey> <PrimaryKeyValue /> <UpdateWhere /> <DeleteWhere /> <Fields> <Field> <!--ID节点表示WinForm/WebForm中控件的ID属性或标准html元素的name属性--> <ID>ID</ID> <!--Name节点表示Select中指定的字段名--> <Name>ID</Name> <Type /> <Save>false</Save> <Visible>false</Visible> </Field> <Field> <ID>Code</ID> <Name>DM</Name> <Align>right</Align> <Width>30</Width> <Type /> <Save>true</Save> <Title>代码</Title> <FormType /> <Visible>true</Visible> <Null>false</Null> <NullTitle>代码不能为空,请输入!</NullTitle> <Sql /> <Value /> <Excel /> <UserInputValue /> </Field> <Field> <ID>Name</ID> <Name>MC</Name> <Title>名称</Title> <NullTitle>名称不能为空,请输入!</NullTitle> </Field> </Fields> </Controller> </WebMisControllerSerializer>
运行原理
假设,在网格的某一行选择后点击编辑按钮或双击网格某一行,弹出一个显示编辑的UI界面(WinForm或Web网页,由使用者或UI设计师开发)。解析程序,会根据XML配置文件中的Select节点获取数据源,通过传递的主键值获取唯一记录,并将记录值根据XML配置的字段映射关系以及与UI中的映射关系,将读取的数据显示在UI中。
如果保存数据,首先判断设置的Null为false时表示不允许为空,根据NullTitle提示用户输入;然后判断如果设置了存在性检查,就会去执行指定的检查规则…;最后,获取字段值以存入数据库。值一般是通过UI元素控件输入,或可以从Excel单元格获取,也可以通过SQL获取,并且优先通过程序配置UserInputValue的键值对设置。
除此之外,系统还会根据一定规则,去读参数值,例如Asp.Net时取URL参数指定值、Session、Application值。
-
控制文件
通过XML描述的控制文件叫控制文件,它可以描述模型定义、UI表单、交互回调函数、查询报表数据源、查询过滤条件字段等。
-
模板文件
使用者自己定义UI界面的页面模板,叫做模板文件,用于输入或显示XML中指定数据源的数据。当然,如果不指定模板文件,可以根据XML控制文件,自动生成页面。
-
解析器
通过XML描述的控制文件,由解析程序来处理并控制的,它会根据控制文件的模型描述,将数据库中数据显示在UI视图中或者将表单数据存储到数据库中。
在本连接下一章节,将用C#实现XML配置文件相关类,并给出源代码。
声明:本文版权为长江支流周方勇所有,如需转载,请保留完整的内容及出处。
作者:长江支流 flygoldfish@163.com 微信:winxin8001234567
连载:(二)循序渐进,通过XML配置,实现通用于WinForm(.Net)、WebForm(Asp.Net+JQuery+EasyUI)表单、报表--原理