创建数据类






4.88/5 (28投票s)
一个应用程序,用于创建 C# 类以读取/写入 Access、SQLite 或 XML 数据库中的数据。
引言
这是一个 C# 类生成器,它将创建一个类文件,用于读写 Access、SQLite 或 XML 格式的数据库。它旨在消除创建此类文件的繁琐工作,这些文件除了字段名称和类型之外,基本上都是样板代码。它可以读取任何上述格式的架构,允许您编辑信息,然后提供更多信息,即可创建 C# 类文件。它也反向工作,允许您在新的或现有的 Access 或 SQLite 数据库中创建表,或为 XML 创建架构文件。输入信息后,您可以将其保存为项目,以便将来轻松进行更改。项目可以保存为 Access 或 SQLite 格式 - Microsoft 提供免费的 Access 2007 运行时,SQLite .NET DLL 可从 SourceForge 获取(详细信息包含在附带的注释中)。
在开始使用程序之前
如果您只读到这里并决定尝试该程序,请务必、务必阅读docs文件夹中的"BEFORE YOU START.txt"文件 - 程序在工作之前需要知道在哪里可以找到其数据库!该文件夹中还有其他值得阅读的文件。
函数
- 您可以创建 C# 类文件来读取/写入经典的 ADO (ADODB)、ADO.NET、SQLite 和 XML 数据库。
- 您可以从现有的 Access、SQLite 或 XML 数据库读取表架构。
- 您可以创建 Access、SQLite 或 XML 表和数据库。
- 您可以将附加字段(例如,数据库中存储的 CSV 字段的计算字段,如
List<T>
)与项目一起保存。 - 您可以将附加函数(即,除了读取/写入数据所需的基本函数之外的函数)与项目一起保存。
- 您可以为每个项目编辑和保存"
using
指令"。 - 您可以生成"标准"原型函数,如清除表单、复制记录、删除记录、保存记录等。这些假定工具栏标签和文本框具有标准命名,如
tslblRecordNumber
、txtHomeAddress
等。 - 它包含一个"数据库资源管理器",以便您可以检查数据库或 XML 架构中表的结构。
- 只要用户定义类型可以转换为公认的数据类型,您就可以在字段中包含它们。
- 您可以将输入的数据保存为项目,以便以后可以重新加载以扩展/更改它。
它是如何工作的?
要能够从一种类型的架构读取数据并将其写入另一种类型,需要一个通用的数据类型。在尝试找到完美的数据类型后,我最终使用了 System.Data.DbType
枚举。项目中包含一个表,其中包含枚举成员名称,每个名称都有一个名为 TypeID 的数字。只要能找到 TypeID,您就可以使用该 TypeID 以高精度查找相应的数据类型。
查找正确的 TypeID 显然是过程的核心。
与 Access 一起使用的 OleDbDataReader
有一个名为"ProviderType"的字段,该字段映射到 ADO 常量,如 adSmallInt
、adInteger
、adSingle
等。这意味着读取 Access 表架构可以提供足够的信息来非常准确地了解字段中的数据类型。项目中包含一个表,它将 Access ProviderType 映射到 TypeID。
读取 XML 架构时提供的信息较少,但 XML 数据库仅使用标准系统类型。SQLiteDataReader
也提供标准系统类型,因此对于 XML 和 SQlite,我都设置了一个表,将系统类型映射到 TypeID。
如果您读取 XML 或 SQLite 架构并希望使用它来创建 Access 表,那么您需要在字段编辑器中微调数据类型,该编辑器允许您通过 System.Data.DbType
枚举选择数据类型。
将字段导入程序
像这样的程序要有用,就必须尽可能轻松地将其字段导入其中。
如果您有现有的 Access、SQLite 或 XML 表/架构,您可以直接将其读入程序。如果您有现有的 C# 类文件,可以使用"导入字段列表"窗体将该文件中的字段列表转换为 C# 类。您还可以导入由 DB 类型枚举、空格、字段名称组成的列表,或者首先是字段名称、然后是 DB 类型枚举的列表。
最后,您可以在"导入字段列表"窗体中手动输入字段,该窗体包含一个包含 DB 类型枚举的组合框和一个用于字段名称的文本框,或者使用字段编辑器逐个输入。
详细信息包含在项目附带的文本文件中。
生成的类文件
如果我们从一个名为 JTestData
的类开始,该程序将生成一个名为JTestData.cs的单个类文件,其中包含
JTestData
类 - 其中还包括一个用于附加字段的区域,因此,如果您将 CSV 数据列表作为字符串保存在数据库中,您可以在此区域添加一个函数将其转换为List<T>
。JTestIndexData
- 一个轻量级的索引类,默认情况下包含 Key Field 和字符串覆盖,但您可以根据需要包含其他字段。这允许您获取一个List<JTestIndexData>
在列表视图或组合框中使用,允许用户轻松选择记录,而无需读取整个数据库。JTestUpdater
- 一个静态类,用于读取/写入数据库,并有一个附加函数区域,您可以在其中放置除读取/写入数据库所需标准函数之外的附加函数。
附加字段和函数会与项目一起保存,因此在重新创建类文件时不会丢失。
当您第一次在 Visual Studio 中打开生成的 C# 类时,它的格式可能不太好。按 Ctrl+K+D(感谢 Frank D 提供此快捷方式)应该可以将其格式化为 Visual Studio 通常格式化文件的方式。C# 源文件中将有一些"TODO"注释。只需检查这些并确保它们符合您的要求。
代码示例
上面提到的 tblDataTypes 表还包括以下字段
ADOConversionPrefix
ADOConversionSuffix
SQLiteConversionPrefix
SQLiteConversionSuffix
SQLiteUpdateSuffix
对于用户定义类型,前缀/后缀存储在字段中,而不是 tblDataTypes
中。在创建类文件时,程序会查找这些前缀/后缀并将它们插入代码中,如下所示:
读取数据
testDataADONET.JDate = Convert.ToDateTime(dataRow["JDate"]);
这相当简单,它将从数据库读取的对象直接转换为 DateTime
。
testDataSQLite.JDate = DateTime.FromBinary(Convert.ToInt64(dataRow["JDate"]));
testDataSQLite.JBoolean = Convert.ToInt32(dataRow["JBoolean"]) > 0;
稍微复杂一点,SQLite 的数据类型有限,因此 DateTime
以 INTEGER
的形式存储,然后程序使用 .NET 函数 DateTime.FromBinary
将 64 位整数转换为 DateTime
。Bool
也以 INTEGER
的形式存储,false 表示零,true 表示其他任何值。
以及 ADO.NET 中的用户定义类型
testDataADONET.JUserDefined =
(JCommon.ClassDataTypes)Convert.ToInt32(dataRow["JUserDefined"]);
这个用户定义的类型实际上是程序中使用的 enum
,它在数据库中以 Int32
的形式存储,并在从数据库读取时转换为用户定义的类型。
写入数据
commandInsert.Parameters.Add(new OleDbParameter("@JDate",testDataADONET.JDate));
commandInsert.Parameters.Add(new SQLiteParameter(
"@JDate",testDataSQLite.JDate.ToBinary()));
commandInsert.Parameters.Add(new SQLiteParameter("@JBoolean",
testDataSQLite.JBoolean ? 1 : 0));
正如您所见,我们使用 .NET 函数将 DateTime
转换为 SQLite 的 INTEGER
。由于 SQLite 没有布尔数据类型,我们输入 1 表示 true,零表示 false。
以及 ADO.NET 中的用户定义类型
commandInsert.Parameters.Add(new OleDbParameter("@JUserDefined",
(Int32)testDataADONET.JUserDefined));
这会将用户定义的类型转换为 Int32
以存储在数据库中。
更新命令的生成方式相同。
正如您所见,程序使用存储在 tblDataTypes
中的转换前缀/后缀来创建命令。程序中有一个用于添加/编辑数据类型的函数,因此可以添加其他类型,或者在需要时更新前缀/后缀。删除数据类型可能不是个好主意,因为您的各个项目可能需要它们。
对于用户定义类型,转换前缀/后缀存储在字段数据中,而不是 tblDataTypes
中。
背景
我几年前写了这个程序,以帮助我将 Access 数据库转换为 XML,然后它就发展起来了。我现在不再将 XML 用于数据库,但我确实编写了许多需要读写数据库的程序,并且我希望有一种快速创建必要类文件的方法。
在早期版本中,我将每个字段的 TypeID 保存在 ListViewItem
的 Tag
中,但这有点不稳定。从第 3 版开始,每个字段都保存为项目数据库中的 JFieldsData
,并通过父记录号链接回已保存的项目。在保存项目之前,父记录号未知,因此为零。保存项目时,它将被更新为实际的父记录号。如果您不保存项目,当您退出程序时,父记录号为零的记录将被删除。
我一直努力从最新版本中消除 bug,并且我更新了使用硬编码字段(如 Record Number)的那些部分,现在它们使用 Key Field。程序现在正确地遵循为每个项目设置的字段的作用域。
我一直在广泛使用该程序,并已尽力修复出现的问题,但大多数程序只有在其他人开始使用时才会出现问题,因此我将非常感谢任何反馈!
程序中内置了一个测试过程,我已经通过了(请参阅Tests文件夹中的Test Process.txt),没有出现问题。
有人建议(由 BigJim61)我考虑使用 CodeDOM,我已经研究过。虽然它对于创建基本类文件非常有用,但在更新程序方面,我最终只使用了代码片段,因此我没有看到使用 CodeDOM 比我使用的 WriteLine
过程有太大的优势。不过,我将来会再看看,因为它看起来确实很有趣。
在我编写该程序的前 3 个版本中,我一直将程序的数据库保存在 LocalUserAppDataPath 中,以使其与 Vista/Win7 兼容。但是,在一次硬盘灾难性故障之后,我现在将其放在了项目文件夹下。我不在"C:"驱动器上存储任何数据,并且知道这一点,我不备份它 - 您可能可以推断出其余的故事!
历史
- 2006 年 12 月 19 日 - 第一个版本。
- 2007 年 11 月 21 日 - 第一次更新。
- 2011 年 1 月 6 日 - 对第 2 版进行了重大更新。
- 2011 年 2 月 2 日 - 再次对第 3 版进行了重大更新。
- 它现在为 SQLite 提供了完全支持。
- 您现在可以声明用户定义的字段类型 - 只要它们可以转换为 DB Enum 类型之一。
- 有一个选项可以预览类文件。
- 已保存项目的的数据格式发生了重大变化。我以前使用逗号分隔列表来存储字段,但增加了 SQLite 和用户定义字段需要更多信息以及更强大的功能。它还便于将来添加其他数据库,例如 SQL。程序中有一个将旧格式的保存项目转换为新格式的函数。
- 2011 年 3 月 1 日 - 对第 4 版进行了又一次重大更新。
- 使用单独的窗体进行用户输入,而不是主窗体上的页面。
- 已清除硬编码的字段名。
- 类作用域已正确遵循。
- 密集 bug 测试。