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

本文涉及的产品
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
云数据库 RDS SQL Server,基础系列 2核4GB
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介:

先有设计,后有代码,改设计总比改代码更容易一些,改设计的成本更低廉,软件也要按图纸施工,没有图纸的建筑物,将来也不好维护,没有数据库设计的软件更怎么可能好维护呢?

 

1:总希望自己的程序能兼容多种数据库,那就尽量用多种数据库都兼容的数据库字段类型来设计表结构。

 

2:将数据库中的表结构能对应到C#的类型里,然后能读取相应的实体字段、按实体的属性写入数据库表中。

 

3:为了测试大容量并发插入表的测试,设计了2个表结构,其中一个用GUID做主键,生成唯一主键,另一个用自增量或者序列做主键。

 

4:代码生成器里,设置了数据库类型与C#的数据类型的对应关系设置及默认值的关系设置等。

代码
         ///   <summary>
        
///  数据库类型映射关系(数据库类型、C#类型、默认值、读取函数)
        
///   </summary>
         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 " }
                                };

        
///   <summary>
        
///  获取字段的类型
        
///   </summary>
        
///   <param name="fieldDataType"> 数据库字段类型 </param>
        
///   <returns> 类型 </returns>
         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;

    
///   <remarks>
    
///  SQLServerExample
    
///  多种数据库兼容的实现方法,只写一套程序在多种数据库上执行例子程序
    
///  
    
///  修改纪录
    
///  
    
///     版本:1.0 2010.06.20    JiRiGaLa    写好例子程序方便别人学习。
    
///     
    
///  版本:1.0
    
///   <author>
    
///          <name> JiRiGaLa </name>
    
///          <date> 2010.06.20 </date>
    
///   </author>  
    
///   </remarks>
     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  +   " <br> " );
            
//  按自增量方式添加数据
            id  =   this .AddEntityByIdentity();
            Page.Response.Write(
" :Identity: "   +  id  +   " <br> " );
        }

        
///   <summary>
        
///  读取图片文件
        
///   </summary>
        
///   <param name="fileName"> 文件名 </param>
        
///   <returns> 字节 </returns>
         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;
        }

        
///   <summary>
        
///  添加实体
        
///   </summary>
        
///   <returns> 主键 </returns>
         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);
        }

        
///   <summary>
        
///  添加实体
        
///   </summary>
        
///   <returns> 主键 </returns>
         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方式生成主键、徐列生成主键完全运行正常,惊喜一下。

代码
<? xml version = " 1.0 " ?>
< configuration >
  
< appSettings >
    
< add key = " RunMode "  value = " Local " />
    
< add key = " ServiceFactory "  value = " ServiceFactory " />
    
< add key = " ServicePath "  value = " DotNet.Service " />

    
< add key = " DbHelperAssmely "  value = " DotNet.DbUtilities " />
    
< add key = " DataBaseType "  value = " Sqlserver " />
    
< add key = " DbHelperClass "  value = " DotNet.DbUtilities.SqlHelper " />
    
< add key = " UserCenterConnection "  value = " Server=JIRIGALA-PC;Database=UserCenterV30;Uid=sa;Pwd=sa; " />

    
<!--
    
< add key = " DataBaseType "  value = " Oracle " />
    
< add key = " DbHelperClass "  value = " DotNet.DbUtilities.OracleHelper " />
    
< add key = " UserCenterConnection "  value = " Data Source = FDAZTC;user id = ztc;password = ztc " />
    
-->

< add key = " BusinessDBConnection "  value = " Data Source=JIRIGALA-PC\SQLEXPRESS;Initial Catalog=ConvenienceServices;Integrated Security=SSPI; " />
    
< add key = " CustomerCompanyName "  value = " 权限学习 " />
    
< add key = " SoftName "  value = " Water " />
    
< add key = " SoftFullName "  value = " 通用权限管理系统 " />
    
< add key = " CompanyFullName "  value = " 杭州吉日软件 " />
    
< add key = " Update "  value = " 2010.06.20 " />
    
< add key = " BugFeedback "  value = " JiRiGaLa_Bao@hotmail.com " />
  
</ appSettings >
  
< connectionStrings >
    
< add name = " Sqlserver "  connectionString = " Server=JIRIGALA-PC;Database=UserCenterV30;Uid=sa;Pwd=sa; "  providerName = " DotNet.DbUtilities.SqlHelper " />
  
</ connectionStrings >
  
< system.web >
    
< compilation debug = " true " >
    
</ compilation >
    
< authentication mode = " Windows " />
    
< customErrors mode = " Off " />
  
</ system.web >
</ configuration >

 

 

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元、服务后,请添加技术支持QQ2520 – 56973,索取相应的程序源码、设计文档等等。

 


本文转自jirigala_bao 51CTO博客,原文链接:http://blog.51cto.com/jirigala/806795

相关文章
|
2天前
|
自然语言处理 数据库 iOS开发
DBeaver Ultimate Edtion 25.0 Multilingual (macOS, Linux, Windows) - 通用数据库工具
DBeaver Ultimate Edtion 25.0 Multilingual (macOS, Linux, Windows) - 通用数据库工具
30 12
DBeaver Ultimate Edtion 25.0 Multilingual (macOS, Linux, Windows) - 通用数据库工具
|
2月前
|
关系型数据库 MySQL 数据库连接
数据库连接工具连接mysql提示:“Host ‘172.23.0.1‘ is not allowed to connect to this MySQL server“
docker-compose部署mysql8服务后,连接时提示不允许连接问题解决
|
13天前
|
SQL 关系型数据库 网络安全
Navicat Premium 17 最新版下载与配置:5分钟完成企业级数据库工具部署
Navicat Premium 17 是一款支持多种主流数据库(如 MySQL、Oracle、PostgreSQL 等)的多数据库管理工具,提供可视化数据建模、SQL 编辑和数据同步等功能。试用版提供 14 天全功能体验,商业版支持跨平台使用。安装环境要求 Windows 10/11 或 macOS 12.0+,最低配置为 4GB 内存。下载并解压安装包后,按步骤启动安装程序、接受许可协议、自定义安装路径并完成安装。首次运行时需激活许可证并配置数据库连接。常见问题包括无法写入注册表、试用期续费及连接数据库权限问题。高级功能涵盖 SSH 通道加速、自动化任务调度和性能调优建议。
94 19
|
21天前
|
关系型数据库 数据库连接 数据库
循序渐进丨MogDB 中 gs_dump 数据库导出工具源码概览
通过这种循序渐进的方式,您可以深入理解 `gs_dump` 的实现,并根据需要进行定制和优化。这不仅有助于提升数据库管理的效率,还能为数据迁移和备份提供可靠的保障。
33 6
|
2月前
|
存储 安全 API
陪玩平台中支付与结算模块的代码,陪玩系统数据库设计与代码实现
第三方支付平台对接涉及与微信支付、支付宝等API接口的调用,确保用户支付流程顺畅。结算模块根据业务规则计算陪玩师收益,强调安全性、异常处理、可扩展性和日志记录。数据库设计涵盖用户、陪玩者、订单等信息的存储管理,确保系统稳定运行。
99 12
|
3月前
|
SQL 程序员 Linux
推荐几个不错的数据库设计工具
推荐几个不错的数据库设计工具
211 11
|
3月前
|
存储 监控 算法
企业内网监控系统中基于哈希表的 C# 算法解析
在企业内网监控系统中,哈希表作为一种高效的数据结构,能够快速处理大量网络连接和用户操作记录,确保网络安全与效率。通过C#代码示例展示了如何使用哈希表存储和管理用户的登录时间、访问IP及操作行为等信息,实现快速的查找、插入和删除操作。哈希表的应用显著提升了系统的实时性和准确性,尽管存在哈希冲突等问题,但通过合理设计哈希函数和冲突解决策略,可以确保系统稳定运行,为企业提供有力的安全保障。
|
3月前
|
存储 关系型数据库 MySQL
double ,FLOAT还是double(m,n)--深入解析MySQL数据库中双精度浮点数的使用
本文探讨了在MySQL中使用`float`和`double`时指定精度和刻度的影响。对于`float`,指定精度会影响存储大小:0-23位使用4字节单精度存储,24-53位使用8字节双精度存储。而对于`double`,指定精度和刻度对存储空间没有影响,但可以限制数值的输入范围,提高数据的规范性和业务意义。从性能角度看,`float`和`double`的区别不大,但在存储空间和数据输入方面,指定精度和刻度有助于优化和约束。
531 5
|
3月前
|
SQL Java 数据库连接
JDBC编程安装———通过代码操控数据库
本文,教你从0开始学习JBCD,包括驱动包的下载安装调试设置,以及java是如何通过JBDC实现对数据库的操作,以及代码的分析,超级详细
|
4月前
|
JSON JavaScript 关系型数据库
node.js连接GBase 8a 数据库 并进行查询代码示例
node.js连接GBase 8a 数据库 并进行查询代码示例