kbmMW已经包含了非常精细的功能来确定和解释数据库中表的元数据。

在下一版本中,这个功能将得到进一步加强,可以导入现有数据库中的表,自动创建与表相匹配的ORM实体类。

这意味着你能够使用kbmMW的ORM智能来查询表,将数据保存回表并操纵表元数据,例如添加,更改或删除字段、索引以及需要能够升级数据库用于匹配已更改的ORM表实体类的更高版本的表。

当你意识到需要更改数据库表以允许其他或不同的字段时,ORM的设计目标之一始终是抽象掉所需的所有枯燥工作。在kbmMW中,它就像更改ORM类一样简单,并使用kbmMW的ORM来创建表的CreateOrUpgrade。这已经在早期的REST相关文章中介绍过。

在下一个即将发布的kbmMW版本中,ORM本身实现了生成Delphi类的代码能力,该代码与ORM实体类对应的任何表相匹配。由于ORM已经支持分析现有的表结构以确定现有的ORM类是否与实际的表结构不同,为了能够自动升级它,它是下一个逻辑步骤,能够使用有关表结构的知识和元数据生成全新的数据库表Delphi实体类。

ImportDBSchema工具实现了ORM实体类的Delphi代码生成,现在我来演示这个工具的用法:

因为复杂的部分已经在kbmMW的内部实现,所以该工具的代码就变的非常简单了。基本上它使用FireDAC支持的任何数据库,包括:SQLite,MSSQL,MySQL,Oracle,Interbase / Firedac和PostgreSQL,用户可以从连接的数据库中选择一个或多个表,然后调用kbmMW的ORM相关代码,最终生成这些表的实体类代码。

表格表示kbmMW语言,从表中建立足够的元数据信息,以便能够使用kbmMW的ORM注册TkbmMWORMTable,启用查询等,而无需实际拥有ORM类。

但由于TkbmMWORMTable包含kbmMW的ORM运行所需的所有元数据,因此它也可以用作生成新ORM表类的源。ORM类显然使您可以非常轻松地将表的字段和记录作为具有属性的常规对象进行访问。

事实上,导入包括生成ORM类的表,归结为调用这两个ORM方法:

var
tbl:TkbmMWORMTable;
begin
...
tbl:=MyORM.SurfaceDynamicTable('actualdbtablename',true);
MyORM.GenerateDelphiClass(tbl...);
...
end;

让我们尝试利用一个MySQL数据库导入一个表。

在这种情况下,我们使用匿名用户名在服务器ensembldb.ensembl.org上选择名为aedes_aegypti_core_48_1b的数据库。

可以在此页面上找到连接信息:https//www.ensembl.org/info/data/mysql.html

单击“连接到数据库”将打开FireDAC对话框,在该对话框中设置数据库的连接信息:

单击“确定”,将显示该数据库中的所有表的列表,选择其中一些表,然后单击“导入所选表”。
现在,系统会提示我们输入单元文件名,用于保存生成的实体类。

由于我们选择了两个表,因此该单元将包含两个类。单击“确定”后,将开始导入。可能需要一段时间。

让我们看看生成的单元,我称之为ensembl.pas

unit ensembl;

interface

uses
DB,
Math,
Classes,
System.Generics.Collections,
kbmMWGlobal,
kbmMWObjectMarshal,
kbmMWNullable,
kbmMWORM,
kbmMWRTTI; type [kbmMW_Table('name:aedes_aegypti_core_48_1b.dna')]
TAedes_aegypti_core__1b_dna = class
private
FSeq_region_id:integer;
FSequence:string;
public
[kbmMW_Field('name:seq_region_id, primary:true', ftInteger)]
[kbmMW_NotNull]
property Seq_region_id:integer read FSeq_region_id write FSeq_region_id; [kbmMW_Field('name:sequence', ftWideMemo)]
[kbmMW_NotNull]
property Sequence:string read FSequence write FSequence; end; [kbmMW_Table('name:aedes_aegypti_core_48_1b.gene')]
TAedes_aegypti_core__1b_gene = class
private
FGene_id:integer;
FBiotype:string;
FAnalysis_id:word;
FSeq_region_id:integer;
FSeq_region_start:integer;
FSeq_region_end:integer;
FSeq_region_strand:byte;
FDisplay_xref_id:kbmMWNullable<integer>;
FSource:string;
FStatus:kbmMWNullable<string>;
FDescription:kbmMWNullable<string>;
FIs_current:byte;
public
[kbmMW_Field('name:gene_id, primary:true', ftInteger)]
[kbmMW_NotNull]
property Gene_id:integer read FGene_id write FGene_id; [kbmMW_Field('name:biotype', ftString, )]
[kbmMW_NotNull]
property Biotype:string read FBiotype write FBiotype; [kbmMW_Field('name:analysis_id', ftSmallInt)]
[kbmMW_NotNull]
property Analysis_id:word read FAnalysis_id write FAnalysis_id; [kbmMW_Field('name:seq_region_id', ftInteger)]
[kbmMW_NotNull]
property Seq_region_id:integer read FSeq_region_id write FSeq_region_id; [kbmMW_Field('name:seq_region_start', ftInteger)]
[kbmMW_NotNull]
property Seq_region_start:integer read FSeq_region_start write FSeq_region_start; [kbmMW_Field('name:seq_region_end', ftInteger)]
[kbmMW_NotNull]
property Seq_region_end:integer read FSeq_region_end write FSeq_region_end; [kbmMW_Field('name:seq_region_strand', ftShortInt)]
[kbmMW_NotNull]
property Seq_region_strand:byte read FSeq_region_strand write FSeq_region_strand; [kbmMW_Field('name:display_xref_id', ftInteger)]
property Display_xref_id:kbmMWNullable<integer> read FDisplay_xref_id write FDisplay_xref_id; [kbmMW_Field('name:source', ftString, )]
[kbmMW_NotNull]
property Source:string read FSource write FSource; [kbmMW_Field('name:status', ftWideString, )]
property Status:kbmMWNullable<string> read FStatus write FStatus; [kbmMW_Field('name:description', ftWideMemo)]
property Description:kbmMWNullable<string> read FDescription write FDescription; [kbmMW_Field('name:is_current', ftShortInt)]
[kbmMW_NotNull]
property Is_current:byte read FIs_current write FIs_current; end; implementation initialization TkbmMWRTTI.EnableRTTI([TAedes_aegypti_core__1b_dna, TObjectList<TAedes_aegypti_core__1b_dna>,
TAedes_aegypti_core__1b_gene, TObjectList<TAedes_aegypti_core__1b_gene>]);
kbmMWRegisterKnownClasses([TAedes_aegypti_core__1b_dna, TObjectList<TAedes_aegypti_core__1b_dna>,
TAedes_aegypti_core__1b_gene, TObjectList<TAedes_aegypti_core__1b_gene>]); end.

您可能会注意到,每个类名都包含架构/数据库名称和表名称。如果您只想将表名作为类名的一部分,请在导入之前选中“不要在类名中包含模式名称”复选框。

在一些相当罕见的情况下,数据库表可能已经定义了某些kbmMW未知的数据类型。在这种情况下,导入仍将发生,但有问题的字段将使用UNKNOWN数据类型进行标记。

kbmMW还尝试确定其他索引和音序器信息,并生成与之匹配的相关属性。然而,如果推断这些类型的信息失败,那么它将被忽略优先级,它将被忽略,因此继续生成基本的ORM表类。

现在,通过将此单元添加到您的应用程序,并设置MySQL kbmMW连接池以指向我们用于导入的相同(或类似)服务器,我们现在可以使用ORM轻松地从这两个表中查询数据。

var
lst:TObjectList<TAedes_aegypti_core__1b_dna>;
begin
lst:=MyORM.QueryList<TAedes_aegypti_core__1b_dna>([],mwoqoGT);
...
end;

在上面的示例中,我们将获得大于2000的主键的TAedes_aegypti_core_48_1b_dna对象列表。

如果对列表中的任何对象进行了任何更改,则可以通过以下方式轻松将更改解析回数据库

MyORM.Persist(lst);

使用ORM,使用这两个表的正确结构创建我们自己的数据库也非常容易。数据库甚至不必是基于MySQL的数据库。它可能是kbmMW的ORM支持的任何一个。

MyOtherORM.CreateOrUpgradeTable([TAedes_aegypti_core__1b_dna,TAedes_aegypti_core__1b_gene])

关于如何以一种新的现代面向对象方式轻松地重用现有数据库,这就结束了这一点。

如果您喜欢我所展示的内容,请通过分享我们的博客和艺术品来传播关于kbmMW的信息。

https://components4developers.blog/2018/11/15/rest-easy-with-kbmmw-17-database-6/

REST easy with kbmMW #17 – Database 6 – Existing databases的更多相关文章

  1. REST easy with kbmMW #3 – SSL

    我在前两篇文章中展示了“REST easy with kbmMW”文章,如何使用kbmMW制作REST服务器,以及如何使用该REST服务器轻松地从数据库返回和存储数据,所有这些都在不到30行的真实数据 ...

  2. REST easy with kbmMW #14 – DB Controlled login

    介绍 关于如何使用授权和登录管理来构建应用服务器还存在一些问题,其中之一就是用户及其角色如何在在数据库中定义.该文将解释使用TkbmMWAuthorizationManager解决此问题的一种方法.有 ...

  3. Use ALTER DATABASE to Move Databases

    Use ALTER DATABASE to Move Databases Follow Our Daily Tips •facebook.com/TechNetTips• twitter.com/Te ...

  4. A SQLiteConnection object for database '/data/data/.../databases/....db' was leaked!

      详细异常: A SQLiteConnection object for database '/data/data/.../databases/....db' was leaked!  Please ...

  5. REST easy with kbmMW #15 – Handling HTTP POST

    我被问到有关如何通过基于kbmMW智能服务(Smart Service)的REST处理POST的问题. 这篇博客文章解释了典型的POST各种形式的访问,以及如何在kbmMW中处理它们. POST变种W ...

  6. REST easy with kbmMW #24 使用kbmMW实现JSON/XML/YAML转换成对象

    你想过没有,把一个给定的xml或json生成一个Delphi类,并通过这个类完成对xml或json的读写操作吗? 不管有没有,现在kbmMW为我们实现了,看下面这行代码: var s:string; ...

  7. REST easy with kbmMW #21 – Delphi client stubs

    在之前的博文中,我提到新的存根生成器框架具有生成Delphi客户端存根所需的功能,使得开发Delphi智能客户端非常容易,完全支持编译时的类型检查和IDE类/属性帮助. 我没想到会把它包含在即将发布的 ...

  8. REST easy with kbmMW #20 – OpenAPI and Swagger UI

    即将推出的kbmMW更新不仅是一些bug修正,同时将包含一个新的主要功能:客户端存根生成器框架. 那什么是客户端存根生成器框架呢? 他是一个基于kbmMW smart services,可以生成由各种 ...

  9. REST easy with kbmMW #16 – Multiple servers using HTTP.sys transport

    前文写过使用HTTP.sys转输层(TkbmMWHTTPSysServerTransport),实现一个kbmMW应用服务器. 如果在一台服务器上,同时运行多个,基于TkbmMWHTTPSysServ ...

随机推荐

  1. DedecmsV5.7本地上传缩略图无法自动添加水印的解决方法

    问题:dedecms后台 系统->图片水印设置 图片水印设置有开启了,但是本地上传缩略图无法自动添加水印 网上有很多资料,所以记录一下 1.打开dede(实际项目后台文件夹)/archives_ ...

  2. Vladik and cards CodeForces - 743E (状压)

    大意: 给定序列, 求选出一个最长的子序列, 使得任选两个[1,8]的数字, 在子序列中的出现次数差不超过1, 且子序列中相同数字连续. 正解是状压dp, 先二分转为判断[1,8]出现次数>=x ...

  3. bzoj3926: [Zjoi2015]诸神眷顾的幻想乡 后缀自动机在tire树上拓展

    题意:有棵树每个点有个颜色(不超过10种),每个节点不超过20个儿子,问你每两点之间的颜色序列不同的有多少种 题解:先建出树,对于每个叶子节点,bfs一遍建在sam上,每次保留当前点在sam上的位置, ...

  4. springboot(十九)使用actuator监控应用

    微服务的特点决定了功能模块的部署是分布式的,大部分功能模块都是运行在不同的机器上,彼此通过服务调用进行交互,前后台的业务流会经过很多个微服务的处理和传递,出现了异常如何快速定位是哪个环节出现了问题? ...

  5. 使用LVM方式安装Ubuntu 16.04

    --- By 小甘丶 注: 这里只讲解如何配置LVM,其他不再陈述! 这个方法,通用的!只要操作系统支持LVM即可!(个人推测,尚未证实) 配置好虚拟机后,开始安装,先进入Ubuntu使用界面,对磁盘 ...

  6. PY3 多组输入

    在c语言你能使用while(scanf(“%d”,x) !=EOF)判断输入是否碰到文件结束符(EOF). 但是在python你不能使用while((x=input())!=EOF). 这有两种方法可 ...

  7. jquery 学习(一):jQuery 简介

    jQuery 库 - 特性: jQuery 是一个 JavaScript 函数库. jQuery 库包含以下特性: html 元素获取, html 元素操作, css 操作, html 事件函数, J ...

  8. OCP知识点讲解 之 检查点队列与增量检查点

    原创 http://blog.chinaunix.net/uid-26762723-id-3271558.html 检查点的主要目的是以对数据库的日常操作影响最小的方式刷新脏块.脏块不断的产生,如何将 ...

  9. JS 控制只能输入数字并且最多允许两位小数点

    <html lang="en"> <head> <meta charset="UTF-8"> <title>JS ...

  10. Java Date实现加一天,年月日类推往后+1,日期+1,月份+1,年份+1

    System.out.println("String类型 "+endDate); //页面传递到后台的时间 为String类型 SimpleDateFormat sdf = new ...