按Sybase的PowerDesigner工具设计的数据库模型 ---> 解析生成能兼容多种数据库的相应的C#底层代码

先有设计,后有代码,改设计总比改代码更容易一些,改设计的成本更低廉,软件也要按图纸施工,没有图纸的建筑物,将来也不好维护,没有数据库设计的软件更怎么可能好维护呢? 1:总希望自己的程序能兼容多种数据库,那就尽量用多种数据库都兼容的数据库字段类型来设计表结构。 2:将数据库中的表结构能对应到C#的类型里,然后能读取相应的实体字段、按实体的属性写入数据库表中。 3:为了测试大容量并发插入表的测试,设计了2个表结构,其中一个用GUID做主键,生成唯一主键,另一个用自增量或者序列做主键。 4:代码生成器里,设置了数据库类型与C#的数据类型的对应关系设置及默认值的关系设置等。 代码 /// /// 数据库类型映射关系(数据库类型、C#类型、默认值、读取函数) /// string [,] DataTypeMapping = { {"NVARCHAR","String", "null", "ToString"}, {"CHAR","String", "null", "ToString"}, {"INT","int", "0", "ToInt"}, {"INTEGER","int", "0", "ToInt"}, {"NUMERIC","Double", "0", "ToDouble"}, {"FLOAT","Double", "0", "ToDouble"}, {"DATE","DateTime?", "null", "ToDateTime"}, {"BLOB","Byte[]", "null", "ToByte"}, {"BFILE","Byte[]", "null", "ToByte"}, {"IMAGE","Byte[]", "null", "ToByte"} }; /// /// 获取字段的类型 /// /// 数据库字段类型 /// 类型 private string GetDataType(string fieldDataType, ref string defaultValue) { // 这是默认值 string returnValue = typeof(string).Name.ToString(); defaultValue = "null"; // 这个是差找对比 for (int i = 0; i < DataTypeMapping.GetLength(0); i++) { if (fieldDataType.IndexOf(DataTypeMapping[i, 0]) >= 0) { returnValue = DataTypeMapping[i, 1]; defaultValue = DataTypeMapping[i, 2]; // 不循环了,提高效率 break; } } return returnValue; } private string GetDataType(string fieldDataType) { // 这是默认值 string returnValue = typeof(string).Name.ToString(); // 这个是差找对比 for (int i = 0; i < DataTypeMapping.GetLength(0); i++) { if (fieldDataType.IndexOf(DataTypeMapping[i, 0]) >= 0) { returnValue = DataTypeMapping[i, 1]; // 不循环了,提高效率 break; } } return returnValue; } private string GetColumnDataType(XmlNode xmlNode, string columnName) { string fieldDataType = string.Empty; for (int i = 0; i < xmlNode.ChildNodes.Count; i++) { if (((XmlNode)xmlNode.ChildNodes[i]).LocalName.Equals("Columns")) { for (int j = 0; j < xmlNode.ChildNodes[i].ChildNodes.Count; j++) { string field = xmlNode.ChildNodes[i].ChildNodes[j].ChildNodes[2].InnerText; if (field.Equals(columnName)) { for (int z = 0; z < xmlNode.ChildNodes[i].ChildNodes[j].ChildNodes.Count; z++) { if (xmlNode.ChildNodes[i].ChildNodes[j].ChildNodes[z].LocalName.Equals("DataType")) { // 字段类型大写 fieldDataType = xmlNode.ChildNodes[i].ChildNodes[j].ChildNodes[z].InnerText.ToUpper(); break; } } break; } } break; } } return GetDataType(fieldDataType); } private string GetConvertFunction(string fieldDataType) { // 这是默认值 string returnValue = "ToString"; // 这个是差找对比 for (int i = 0; i < DataTypeMapping.GetLength(0); i++) { if (fieldDataType.IndexOf(DataTypeMapping[i, 0]) >= 0) { returnValue = DataTypeMapping[i, 3]; // 不循环了,提高效率 break; } } return returnValue; } 5:接下来需要用代码生成器生成相应的代码,这时候比较麻烦的事情有以下几个: A:guid做主键时,为了兼容多种数据库,用了字符类型字段,用自增量时,主键为整数类型,这里需要有一定的技术水平需要处理一下。 B:用自增量做主键时,不同的数据库的处理方式不一样,这时候需要考虑写同一套代码,能兼容多种数据库的问题,程序的写法是一样同时能能支持多种数据库。 6:为了测试多种数据库上的兼容性,现在以 Oracle、SQLServer 为主要目标来进行测试,创建数据库的脚本如下: UserByGUID.Oracle.SQL (Oracle按GUID为主键模式) 代码 -- Create table create table USERBYGUID ( ID NVARCHAR2(50), FULLNAME NVARCHAR2(50), SALARY NUMBER(10,2) default 0, AGE NUMBER(2) default 0, BIRTHDAY DATE, PHOTO BLOB, ALLOWEDIT NUMBER(1) default 1, ALLOWDELETE NUMBER(1) default 1, ENABLED NUMBER(1) default 1, DELETEMARK NUMBER(1) default 0, DESCRIPTION NVARCHAR2(200), CREATEDATE DATE default sysdate, CREATEUSERID NVARCHAR2(50), CREATEUSERREALNAME NVARCHAR2(50), MODIFYDATE DATE default sysdate, MODIFYUSERID NVARCHAR2(50), MODIFYUSERREALNAME NVARCHAR2(50) ); UserByInt.Oracle.SQL (Oracle按序列为主键模式) 代码 -- Create sequence create sequence SEQ_USERBYINT minvalue 1 maxvalue 999999999999999999999999999 start with 21 increment by 1 cache 20; -- Create table create table USERBYINT ( ID NUMBER, FULLNAME NVARCHAR2(50), SALARY NUMBER(10,2) default 0, AGE NUMBER(2) default 0, BIRTHDAY DATE, PHOTO BLOB, ALLOWEDIT NUMBER(1) default 1, ALLOWDELETE NUMBER(1) default 1, ENABLED NUMBER(1) default 1, DELETEMARK NUMBER(1) default 0, DESCRIPTION NVARCHAR2(200), CREATEDATE DATE default sysdate, CREATEUSERID NVARCHAR2(50), CREATEUSERREALNAME NVARCHAR2(50), MODIFYDATE DATE default sysdate, MODIFYUSERID NVARCHAR2(50), MODIFYUSERREALNAME NVARCHAR2(50) ); UserByGUID.SQLServer.SQL (SQLServer按GUID为主键模式) 代码 CREATE TABLE [dbo].[UserByGUID]( [Id] [nvarchar](50) NOT NULL, [FullName] [nvarchar](50) NULL, [Salary] [numeric](10, 2) NULL DEFAULT ((0)), [Age] [int] NULL DEFAULT ((0)), [Birthday] [smalldatetime] NULL DEFAULT (getdate()), [Photo] [image] NULL, [AllowEdit] [int] NULL DEFAULT ((1)), [AllowDelete] [int] NULL DEFAULT ((1)), [Enabled] [int] NULL DEFAULT ((1)), [DeleteMark] [int] NULL DEFAULT ((0)), [Description] [nvarchar](50) NULL, [CreateDate] [smalldatetime] NULL DEFAULT (getdate()), [CreateUserId] [nvarchar](50) NULL, [CreateUserRealname] [nvarchar](50) NULL, [ModifyDate] [smalldatetime] NULL DEFAULT (getdate()), [ModifyUserId] [nvarchar](50) NULL, [ModifyUserRealname] [nvarchar](50) NULL, CONSTRAINT [PK_USERBYGUID] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] UserByInt.SQLServer.SQL (SQLServer自增量方式) 代码 CREATE TABLE [dbo].[UserByInt]( [Id] [int] IDENTITY(1,1) NOT NULL, [FullName] [nvarchar](50) NULL, [Salary] [numeric](10, 2) NULL DEFAULT ((0)), [Age] [int] NULL DEFAULT ((0)), [Birthday] [smalldatetime] NULL DEFAULT (getdate()), [Photo] [image] NULL, [AllowEdit] [int] NULL DEFAULT ((1)), [AllowDelete] [int] NULL DEFAULT ((1)), [Enabled] [int] NULL DEFAULT ((1)), [DeleteMark] [int] NULL DEFAULT ((0)), [Description] [nvarchar](50) NULL, [CreateDate] [smalldatetime] NULL DEFAULT (getdate()), [CreateUserId] [nvarchar](50) NULL, [CreateUserRealname] [nvarchar](50) NULL, [ModifyDate] [smalldatetime] NULL DEFAULT (getdate()), [ModifyUserId] [nvarchar](50) NULL, [ModifyUserRealname] [nvarchar](50) NULL, CONSTRAINT [PK_USERBYINT] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 7:用代码生成器,生成相关的类代码: 8:代码复制到工程文件里的效果如下: 9:编写自动化测试程序如下 代码 //------------------------------------------------------------ // All Rights Reserved , Copyright (C) 2010 , Jirisoft , Ltd. //------------------------------------------------------------ using System; using System.IO; namespace DotNet.Web.Permission { using DotNet.Utilities; /// /// SQLServerExample /// 多种数据库兼容的实现方法,只写一套程序在多种数据库上执行例子程序 /// /// 修改纪录 /// /// 版本:1.0 2010.06.20 JiRiGaLa 写好例子程序方便别人学习。 /// /// 版本:1.0 /// /// JiRiGaLa /// 2010.06.20 /// /// public partial class SQLServerExample : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { string id = string.Empty; // 按GUID方式添加数据 id = this.AddEntityByGUID(); Page.Response.Write(":GUID:" + id + "
"); // 按自增量方式添加数据 id = this.AddEntityByIdentity(); Page.Response.Write(":Identity:" + id + "
"); } /// /// 读取图片文件 /// /// 文件名 /// 字节 private byte[] GetFile(string fileName) { FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read); BinaryReader binaryReader = new BinaryReader(fileStream); byte[] file = binaryReader.ReadBytes(((int)fileStream.Length)); binaryReader.Close(); fileStream.Close(); return file; } /// /// 添加实体 /// /// 主键 private string AddEntityByGUID() { // 这个是管理器 UserByGUIDManager userByGUIDManager = new UserByGUIDManager(); // 不要自增量 // userByGUIDManager.Identity = false; // 这个是实体 UserByGUIDEntity userByGUIDEntity = new UserByGUIDEntity(); userByGUIDEntity.Id = BaseBusinessLogic.NewGuid(); userByGUIDEntity.FullName = "吉日嘎拉"; userByGUIDEntity.Salary = 15000.00; userByGUIDEntity.Age = 33; userByGUIDEntity.AllowDelete = 1; userByGUIDEntity.AllowEdit = 1; userByGUIDEntity.Birthday = new DateTime(1978, 5, 19); userByGUIDEntity.DeleteMark = 0; userByGUIDEntity.Enabled = 1; userByGUIDEntity.Photo = this.GetFile(@"C:/Users/jirigala/Pictures/01.jpg"); // 这里是添加操作 return userByGUIDManager.Add(userByGUIDEntity); } /// /// 添加实体 /// /// 主键 private string AddEntityByIdentity() { // 这个是管理器 UserByIntManager userByIntManager = new UserByIntManager(); // 是要自增量 // userByIntManager.Identity = true; // 不用返回 // userByIntManager.ReturnId = false; // 这个是实体 UserByIntEntity userByIntEntity = new UserByIntEntity(); userByIntEntity.FullName = "吉日嘎拉"; userByIntEntity.Salary = 15000.00; userByIntEntity.Age = 33; userByIntEntity.AllowDelete = 1; userByIntEntity.AllowEdit = 1; userByIntEntity.Birthday = new DateTime(1978, 5, 19); userByIntEntity.DeleteMark = 0; userByIntEntity.Enabled = 1; userByIntEntity.Photo = this.GetFile(@"C:/Users/jirigala/Pictures/01.jpg"); // 这里是添加操作 return userByIntManager.Add(userByIntEntity, true); } } } 10:同样的程序,修改配置文件,连接到Oracle数据库上,GUID方式生成主键、徐列生成主键完全运行正常,惊喜一下。 代码 11:PowerDesigner设计的PDM文件下载,请在此下载 /Files/jirigala/CodeBuilder.pdm.rar 12:完整的例子程序下载,请在此下载,若有缺少的DLL引用,可以在从目录DotNet.Web.Permission/Resource/External 里进行重新饮用 /Files/jirigala/DotNet.Web.Permission.rar 13:在淘宝网店地址 http://shop59297253.taobao.com/ 上购买相应的功能软件,此强大的代码生成器仅销售RMB:100元、服务后,请添加技术支持QQ:2520 – 56973,索取相应的程序源码、设计文档等等。 一步步教你如何用疯狂.NET架构中的通用权限系统 -- 如何控制用户显示的菜单权限 一步步教你如何用疯狂.NET架构中的通用权限系统 -- 在页面中的调用权限讲解 一步步教你如何用疯狂.NET架构中的通用权限系统 -- 数据集权限的调用权限讲解 一步步教你如何用疯狂.NET架构中的通用权限系统 -- 分级管理 一步步教你如何用疯狂.NET架构中的通用权限系统 -- 分级授权 疯狂.NET 通用权限设计 C/S后台管理,B/S前台调用源码样例程序源码下载之 --- 操作权限 疯狂.NET 通用权限设计 C/S后台管理,B/S前台调用源码样例程序源码下载之 --- 角色权限 疯狂.NET 通用权限设计 C/S后台管理,B/S前台调用源码样例程序源码下载之 --- 数据集权限 将权限管理、工作流管理做到我能力的极致,一个人只能做好那么很少的几件事情。 吉日嘎拉 不仅权通用权限 关注 - 128 粉丝 - 332 关注博主2 2 0 (请您对文章做出评价)« 上一篇:若3行代码能改进简化为1行代码,那对整个公司会有多少影响? » 下一篇:【浙大网新图灵通讯】无废话简单高效C#编码规范20100621 posted on 2010-06-20 23:20 吉日嘎拉 不仅权通用权限 阅读(573) 评论(2) 编辑 收藏 评论 1854840 #1楼  回复 引用 查看  结合PowerDesigner不错 2010-06-23 16:24 | 伍华聪 #2楼[楼主]  回复 引用 查看  @伍华聪 你这家伙,都不按一下推荐,哈哈。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值