连载:(二)循序渐进,通过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 微信:weixin8001234567