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

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
公共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

相关文章
|
1月前
|
数据库 索引
深入探索数据库索引技术:回表与索引下推解析
【10月更文挑战第15天】在数据库查询优化的领域中,回表和索引下推是两个核心概念,它们对于提高查询性能至关重要。本文将详细解释这两个术语,并探讨它们在数据库操作中的作用和影响。
50 3
|
2月前
|
开发框架 供应链 监控
并行开发模型详解:类型、步骤及其应用解析
在现代研发环境中,企业需要在有限时间内推出高质量的产品,以满足客户不断变化的需求。传统的线性开发模式往往拖慢进度,导致资源浪费和延迟交付。并行开发模型通过允许多个开发阶段同时进行,极大提高了产品开发的效率和响应能力。本文将深入解析并行开发模型,涵盖其类型、步骤及如何通过辅助工具优化团队协作和管理工作流。
66 3
|
2月前
|
存储 SQL 关系型数据库
Mysql学习笔记(二):数据库命令行代码总结
这篇文章是关于MySQL数据库命令行操作的总结,包括登录、退出、查看时间与版本、数据库和数据表的基本操作(如创建、删除、查看)、数据的增删改查等。它还涉及了如何通过SQL语句进行条件查询、模糊查询、范围查询和限制查询,以及如何进行表结构的修改。这些内容对于初学者来说非常实用,是学习MySQL数据库管理的基础。
134 6
|
2月前
|
存储 NoSQL 关系型数据库
数据库技术深度解析:从基础到进阶
【10月更文挑战第17天】数据库技术深度解析:从基础到进阶
78 0
|
2月前
|
SQL 关系型数据库 MySQL
数据库导入SQL文件:全面解析与操作指南
在数据库管理中,将SQL文件导入数据库是一个常见且重要的操作。无论是迁移数据、恢复备份,还是测试和开发环境搭建,掌握如何正确导入SQL文件都至关重要。本文将详细介绍数据库导入SQL文件的全过程,包括准备工作、操作步骤以及常见问题解决方案,旨在为数据库管理员和开发者提供全面的操作指南。一、准备工作在导
349 0
|
1月前
|
存储 负载均衡 监控
数据库多实例的深入解析
【10月更文挑战第24天】数据库多实例是一种重要的数据库架构方式,它为数据库的高效运行和灵活管理提供了多种优势。在实际应用中,需要根据具体的业务需求和技术环境,合理选择和配置多实例,以充分发挥其优势,提高数据库系统的性能和可靠性。随着技术的不断发展和进步,数据库多实例技术也将不断完善和创新,为数据库管理带来更多的可能性和便利。
100 57
|
29天前
|
编译器 C# 开发者
C# 9.0 新特性解析
C# 9.0 是微软在2020年11月随.NET 5.0发布的重大更新,带来了一系列新特性和改进,如记录类型、初始化器增强、顶级语句、模式匹配增强、目标类型的新表达式、属性模式和空值处理操作符等,旨在提升开发效率和代码可读性。本文将详细介绍这些新特性,并提供代码示例和常见问题解答。
39 7
C# 9.0 新特性解析
|
1月前
|
SQL 关系型数据库 数据库
国产数据实战之docker部署MyWebSQL数据库管理工具
【10月更文挑战第23天】国产数据实战之docker部署MyWebSQL数据库管理工具
108 4
国产数据实战之docker部署MyWebSQL数据库管理工具
|
23天前
|
存储 网络协议 安全
30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场
本文精选了 30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场。
65 2
|
23天前
|
存储 安全 Linux
Golang的GMP调度模型与源码解析
【11月更文挑战第11天】GMP 调度模型是 Go 语言运行时系统的核心部分,用于高效管理和调度大量协程(goroutine)。它通过少量的操作系统线程(M)和逻辑处理器(P)来调度大量的轻量级协程(G),从而实现高性能的并发处理。GMP 模型通过本地队列和全局队列来减少锁竞争,提高调度效率。在 Go 源码中,`runtime.h` 文件定义了关键数据结构,`schedule()` 和 `findrunnable()` 函数实现了核心调度逻辑。通过深入研究 GMP 模型,可以更好地理解 Go 语言的并发机制。

推荐镜像

更多