65.9K
CodeProject 正在变化。 阅读更多。
Home

Paradox 数据库原生 .NET 读取器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (29投票s)

2010年8月11日

CPOL

4分钟阅读

viewsIcon

221104

downloadIcon

5357

在纯 .NET 代码中读取 Paradox 数据库的内容,无需使用 BDE 或其他库;包含索引支持。

引言

如果您正在开发访问 Paradox 数据库的软件,您可能正在使用 BDE (Borland Database Engine)。本文展示了如何使用 Paradox 数据库文件并直接从中读取一些数据。您还可以使用主索引来查找您需要的特定记录。如果 BDE 与您不合作,或者您不能或不想使用 BDE,这可能很有用。

背景

每个开发人员有时都必须处理某种黑盒 - 一种未公开的技术,只能通过某些外部接口访问,但存在一个问题 - 这个黑盒对我们来说非常神秘 - 有时它有效,有时它无效,无论你做什么,它似乎都有自己的情绪。然后我总是希望它能被打开,这样我就可以调试它,跟踪它,看看它的内部结构。您也是一个在快速链接之间有 Reflector 的开发人员吗?那么您可能会理解我为什么开始搜索一些 .NET 原生 Paradox 数据库读取器。我找不到任何一个,但我找到了一些 Paradox 格式规范,所以我决定自己编写一个并公开它,供其他人使用。非常感谢 Randy Beck 和 Kevin Mitchell 分享了 Paradox 内部结构,并且由于他们的材料是在线的,我将把精力集中在描述我自己的代码上。

Paradox 使用数据库对象将数据拆分到文件中 - 每个表都有自己的文件,每个索引也是如此。数据文件和索引具有非常相似的结构,因此我们可以在一个类中同时处理它们 - ParadoxFile。BLOB 值也存储在它们自己的文件中,但我还没有实现该结构。

  • ParadoxFile - 处理 Paradox 数据文件和索引中通用结构的基础类
  • ParadoxFile.DataBlock - 表示一个数据块
  • ParadoxFile.FieldInfo - 字段的数据类型
  • ParadoxFile.V4Hdr - 仅存在于某些 Paradox 文件/版本中的结构
  • ParadoxTable - 表示表数据文件
  • ParadoxPrimaryKey - 表示表索引
  • ParadoxFileType - 包含所有文件类型的枚举
  • ParadoxFieldType - 包含所有数据类型的枚举
  • ParadoxRecord - 表示一条数据记录
  • ParadoxDataReader - 标准 IDataReader 实现

实际上,索引文件只是一个包含数据块索引和相关索引值的表。您可以直接读取它,但我也创建了一个机制,可以为您浏览索引树并选择所需的记录。您只需指定您想要应用于数据的条件。

  • ParadoxCondition - 可用于在索引数据中搜索的条件的基础类
  • ParadoxCondition 嵌套类 - 各种条件实现
  • ParadoxCompareOperator - 包含支持的比较运算符(==, !=, <, <=, >, >=)的枚举

Class diagram

使用代码

一种方法是直接打开一个表并开始枚举。这是通过以下代码段完成的。我们将创建一个 ParadoxTable 对象并使用 Enumerate 方法遍历记录。数据根据需要同步检索,因此如果我们在读取几个记录后停止读取,则不会执行冗余读取操作。

var table = new ParadoxTable(dbPath, "zakazky");
var recIndex = 1;
foreach (var rec in table.Enumerate())
{
    Console.WriteLine("Record #{0}", recIndex++);
    for (int i=0; i<table.FieldCount; i++)
    {
        Console.WriteLine("    {0} = {1}", table.FieldNames[i], rec.DataValues[i]);
    }
    if (recIndex > 10) break;
}

当然,在某些情况下,这种简单的方法是不够的。有时我们还必须读取大型数据库中间的某些数据,因此我们需要使用索引来最大限度地减少磁盘操作。在下一个示例中,我们将使用主键索引来查找键值在 1750 和 1760 之间的记录。首先,必须打开索引文件,然后我们将创建一个由两个比较操作组成的条件。我们可以通过调用索引上的 Enumerate 方法来浏览数据。在这种情况下,我们将使用具有 IDatareader 实现的 ParadoxDataReader 类,因此如果之前使用过 BDE,则无需重写大量代码。

var index = new ParadoxPrimaryKey(table, Path.Combine(dbPath, "zakazky.PX"));
var condition =
    new ParadoxCondition.LogicalAnd(
        new ParadoxCondition.Compare(
            ParadoxCompareOperator.GreaterOrEqual, 1750, 0, 0),
        new ParadoxCondition.Compare(
            ParadoxCompareOperator.LessOrEqual, 1760, 0, 0));
var qry = index.Enumerate(condition);
var rdr = new ParadoxDataReader(table, qry);
recIndex = 1;
while (rdr.Read())
{
    Console.WriteLine("Record #{0}", recIndex++);
    for (int i = 0; i < rdr.FieldCount; i++)
    {
        Console.WriteLine("    {0} = {1}", rdr.GetName(i), rdr[i]);
    }
}

限制

  • 只读解决方案
  • 并非所有数据类型都受支持
  • 没有 SQL、LINQ 或其他复杂查询
  • 在写入期间,您不应该使用活动的数据库

历史

  • 1.0 - 初始版本
  • 1.1 - 更新了 Number 数据类型支持(感谢 Tonki)
  • 1.2 - 附加数据类型支持(感谢 Mark Kuin、Christopher Erker 和 Tonki 再次感谢)
© . All rights reserved.