开发者社区> 科技小能手> 正文

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

简介:
+关注继续查看

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

 

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,2default 0,
  AGE                NUMBER(
2default 0,
  BIRTHDAY           DATE,
  PHOTO              BLOB,
  ALLOWEDIT          NUMBER(
1default 1,
  ALLOWDELETE        NUMBER(
1default 1,
  ENABLED            NUMBER(
1default 1,
  DELETEMARK         NUMBER(
1default 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,2default 0,
  AGE                NUMBER(
2default 0,
  BIRTHDAY           DATE,
  PHOTO              BLOB,
  ALLOWEDIT          NUMBER(
1default 1,
  ALLOWDELETE        NUMBER(
1default 1,
  ENABLED            NUMBER(
1default 1,
  DELETEMARK         NUMBER(
1default 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](
102) 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](
102) 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(1978519);
            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(1978519);
            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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
分析与设计数据库模型的简单过程
原文:分析与设计数据库模型的简单过程 近期在做一个业务系统的分析和数据模型设计,工作这几年也做过好几个项目的数据库模型的设计,期间也算是积累了一定的经验吧,这次有机会就写写我的数据库模型设计过程与方法。
1126 0
HiTSDB 时序数据库技术架构和产品解析
8月24日阿里云数据库技术峰会上,来自阿里数据库事业部高级专家钟宇带来HiTSDB 时序数据库方面的演讲。本文主要从时序数据开始介绍,包括时序序列数据的特点,接着介绍了时序数据业务场景,以及OpenTSDB在HBase上的优化,最后分享了HiTSDB的优化和提高。
9034 0
ML之FE:基于load_mock_customer数据集(模拟客户)利用featuretools工具实现自动特征生成/特征衍生
ML之FE:基于load_mock_customer数据集(模拟客户)利用featuretools工具实现自动特征生成/特征衍生
66 0
黑客炼金术士 Seeker:可以攻破 4G 摸到你短信,还要为朝阳群众提供谍战工具
在北京上地的一家咖啡馆里,我在等待黑客 Seeker 的到来。 我对黑客 Seeker 颇有期待。他曾在黑客大会 KCon 上演讲《伪基站高级利用技术——彻底攻破短信验证码》,介绍利用 LTE/4G 伪基站+GSM 中间人攻击来攻破所有短信验证码。
1546 0
对象的继承关系在数据库中的实现方式和PowerDesigner设计
原文:对象的继承关系在数据库中的实现方式和PowerDesigner设计 在面向对象的编程中,使用对象的继承是一个非常普遍的做法,但是在关系数据库管理系统RDBMS中,使用的是外键表示实体(表)之间的关系,那么对于继承关系,该怎么在RDBMS中表示呢?一般来说有3种实现方式: Concrete ...
905 0
DBImport v3.5 中文版发布:数据库定时同步及文档生成工具(IT人员必备)
前言: 趁着最近的休息时间,只能多勤快些:多写代码,多更新文章。 因为一旦投入新的工作,估计博客又会恢复到一年才产几篇的状态。 对于DBImport,因为用户的意见,增加了一个亮点功能,让软件B格升为数据库时时同步工具,所以值的介绍一下。
1171 0
MyBatis框架使用解析!数据库相关API的基本介绍
本篇文章中对MyBatis框架中的具体使用进行了详细的分析说明。介绍了在Java项目使用的各种API的基本方式。包括动态SQL,多数据库支持,脚本语言,Java中各种语句执行方法,SELECT语句的高级使用,清除批量更新的方法以及事务控制的方法。
50 0
23704
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载