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

让您的桌面数据库应用程序更好的10件事

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (14投票s)

2010年2月22日

CPOL

11分钟阅读

viewsIcon

35931

这里有10件事可以使您的桌面数据库应用程序更好

注意:本文最初发布在VistaDB博客上,但已永久移至此位置

这些项目中的每一个都可以单独写一篇博客文章,但我会非常努力地不冗长,只涵盖概念的核心以及为什么你需要这样做。

数据驱动应用程序依赖于其数据库

每个人都知道,任何由数据驱动的应用程序都不仅仅是应用程序本身。在大多数情况下,没有数据库的应用程序甚至无法运行,或者无法正常运行。如果数据库是应用程序不可或缺的一部分,那么您难道不应该尽一切可能确保其健康并为最坏的损坏或硬盘故障事件做好准备吗?

本周,我们收到了5位长期用户的联系,他们突然丢失或损坏了数据。其中两例是最终用户数据,需要花费大量的精力才能重现。在所有这些情况下,以下简单的步骤本可以完全避免这种情况。

1. 备份您的数据库

这看起来很明显,对吧?数据库只是一个文件,xcopy一下就可以进行备份。在您的应用程序中强制执行备份,使其成为应用程序不可或缺的一部分。如果用户意外删除了大量数据,您如何恢复?有了备份,就很容易了。

示例策略

当您的应用程序启动时,在子文件夹中创建数据库备份。一个简单的名称,例如您应用程序目录中的\backups。如果您想更高级,您甚至可以在其下为YYYY-MM创建一个子目录,或者当您备份数据库时,将其重命名为DatabaseName-YYYY-MM.vdb4。这样您就可以轻松地向用户显示目录中的备份,并让他们选择一个进行恢复。

为了防止备份无限增长,您可以定期汇总所有备份的大小,并删除最旧的备份,直到低于某个大小阈值。我几乎可以向您保证,现在大多数用户拥有100MB的磁盘空间用于备份并不是什么大问题。如果这能为他们提供一个月的备份,那么如果将来发生不好的事情,他们会非常感谢您。

2. 确保单用户应用程序中的干净关闭检测

您是否曾在运行Microsoft Outlook时遇到过崩溃?当它重新启动时会发生什么?Outlook将重新验证PST文件以确保其未损坏。

每个打开数据库连接的应用程序都应该有某种方法来检测它是否干净关闭。这是您唯一能知道应用程序是否已终止(无论是用户终止、崩溃还是操作系统终止)的方法。

请记住,VistaDB存在于您的应用程序内部。所以当您的应用程序崩溃时,引擎也会崩溃。服务器系统不必担心这个问题,因为服务器服务仍然是唯一与文件通信的东西。

示例策略

我通常在启动时包含一个注册表键的检查。如果注册表键在启动时仍然存在,那么应用程序要么仍在本地运行,要么上次运行时没有干净关闭。我将注册表键的清除功能作为应用程序退出前发生的最后一件事。不是在我想要退出的时候(您仍然可能在尝试干净关闭时崩溃),而是在实际退出之前。

在C#程序中,您可以在Program Main函数中执行此操作。始终在应用程序的主运行周围放置一个try / catch块,然后添加一个清除关闭的finally块。

如果您想要一个出色的工具来帮助捕获其他应用程序错误并报告它们,我建议使用Gibraltar Software。他们已经使将通用错误捕获系统集成到几乎任何应用程序中变得非常容易。

3. 确保多用户应用程序中的干净关闭检测

多用户应用程序更难跟踪,因为在应用程序失败或终止(或操作系统崩溃等)时,您可能不是数据库中唯一的用户。您仍然应该遵循上述方法来检测您的实际应用程序是否正确关闭,但现在您必须在打包/清理情况周围添加更复杂的逻辑。

示例策略

我们通过在一些项目上添加一个System_Settings表来部署了一个相当简单的策略。这个设置表通常只包含一行,但包含上次备份的时间信息(以防止每个应用程序在启动时都尝试备份),以及数据库是否有脏关闭。当脏标志被设置(从共享模式)时,应用程序然后尝试以独占方式打开数据库进行打包。根据您的应用程序,您可以从其他桌面在应用程序内部定期检查此情况,如果看到该标志,则在一段时间内释放所有连接,然后再次尝试访问数据库。

根据您的应用程序设计,您可以有很多不同的方法来做到这一点。您还可以将一个平面文件(如dirty.txt)放在数据库旁边,每个连接类在打开数据库之前都进行检查,等等。重要的是要确保检测到脏关闭,并且无需用户干预即可恢复。

4. 处理代码中的异常

请参阅Gibraltar Software页面,了解可帮助您在代码中随处执行此操作的软件。但即使您不使用他们的软件,您仍然需要确保在可能出现问题的地方进行处理。

如果在插入过程中磁盘空间不足怎么办?如果更新行引发并发异常怎么办?确保您处理这些情况。

示例策略

最简单的方法是将您的数据库函数封装到数据访问层(DAL)中。它不必是应用程序之外的单独程序集。只需确保您有一种统一的方式访问数据库并可以捕获所有错误。记录它们以确保意外的错误可以轻松地报告给您,即使用户必须在目录中找到一个名为“Errors.txt”的平面文件并将其通过电子邮件发送给您,那也比什么都没有强。

5. 将所有对象放入 using() 语句中

许多Microsoft的示例都应该展示这种最佳实践,但它们没有。我个人认为它并没有增加示例的可读性,而且它是一种最佳实践。所以它应该始终被展示出来。

基本上,任何时候您分配一个具有处置方法(disposing)的对象时,都应该将其放入using()块中。这可以确保GC会尽快清理它。在对象上调用.Close()并将其设置为nothing或null是不同的。您必须调用.Close().Dispose(),然后确保所有引用都已消失。

示例策略

using (VistaDB.Provider.VistaDBDataReader reader = command.ExecuteReader())
{
   while (reader.Read())
   {
     // Do something
   }
}

这一件事将极大地减少您的内存问题,修复出现的虚假错误,以及更多。我通过简单地在客户的对象分配周围添加using()解决了许多客户问题。VistaDB是100%托管代码,如果您不清理我们,或者持有对我们的引用,对象可能会在RAM中停留很长时间。

6. 仅在需要时使用事务

事务对于基于文件的数据库来说非常昂贵,非常昂贵。不要使用它们来更新单个表中的单个条目,或仅仅为了运行select查询而创建事务。仅在有意义时使用它们。

此外,请阅读我们博客上关于事务会损害性能的文章。

7. 仅在需要时加密,不要用于密码控制

这通常来自以前的Access程序员。Access有这样一个概念,即通过最终用户在其自己的Access副本中打开文件进行控制的密码。VistaDB不需要这样的概念。在VistaDB 4中,我们将名称从密码更改为加密短语,以更清楚地表明密码用于加密。

加密将基本短语添加盐值,然后在写入时加密每个页面,并在加载时解密。这非常昂贵(30%或更多的开销),如果您的数据库损坏,我们无法恢复加密数据(这会失去加密的目的)。

您可以为数据库开启加密,然后如果只需要加密单个表,可以为某些表关闭加密。但这仍然会使磁盘上的所有头文件加密,并且无法恢复。

8. 使用干净的副本进行调试

不要针对生产数据库进行调试(永远不要!)。特别是在运行NUnit等测试时,您总是希望从已知状态开始。最简单的方法是将一个预填充的数据库放在应用程序目录中,并在Visual Studio中设置选项,始终将其复制到输出目录。这样,在每次构建时,您的调试目录中都有一个干净的数据库。

这可能是人们损坏数据库的头号方式。在大量活动时停止并杀死引擎最终会导致损坏。尝试每次停止调试时杀死SQL Server,我保证在足够的迭代后您会得到一个损坏的数据库。

9. 确保数据库的定期维护

在您的应用程序中创建一个定期维护周期。应用程序可以每周、每月执行此操作,或者基于某些内部定义的“使用”情况。如果您知道每次运行您的应用程序都会产生10%的数据周转,那么您应该每10次运行打包一次,以使数据库保持最小大小和最佳格式。

示例策略

在您的数据库中添加一个SYSTEM_MAINTENANCE表,该表只有一行。LASTPACKED DateTime。仅此一个字段将帮助您确定上次清理数据库的时间。您可以允许用户执行,或提示他们,或者如果您知道用户活动处于低点,则在后台执行。

重要的是要有定期维护数据库的计划。SQL Server内置了这些维护计划,以定期执行索引重建等操作。我们没有这种能力,因为我们只在您运行时运行,而且我们永远不知道运行会持续多久。

10. 为组件的定期更新做好准备

有一种方法可以向您的用户部署更新。您最终会遇到一个所有用户都需要避免的错误,或者来自供应商(例如我们)的更新组件。如果您无法发布该更新,您将会遇到一些不高兴的用户。

VistaDB会定期更新,我相信您的其他供应商也是如此。我们发布更新并非没有原因。几乎每个版本都有修复和更新。您不必急于部署新的主版本或次版本,但您major.minor中的版本应该被视为必要的维护更新。

有时客户会联系我们,反映他们从未更新过的VistaDB 3.0版本的问题。抱歉,我们会定期发布更新,将其发布到网站上,列在RSS订阅、博客文章等中。有很多方法可以查看和获取更新。如果您正在运行VistaDB 3.5并且仍然使用最初的版本,那么您没有获取最新版本是在害自己。

您正在使用的任何超过12个月未更新的供应商产品要么已死(没有新的开发),要么已过时,要么本质上非常琐碎。

示例策略

选择一个日期(微软使用每月的第一个星期二)来访问您的所有供应商。看看他们是否有更新,阅读发布说明。计划将它们集成到您的下一个版本中进行测试。如果任何供应商的更新是关键的,那么您也需要执行关键更新。

确保您有一种向用户提供更新的方法。您不必自己编写所有这些,Tarma Installer提供了一种非常简单的方法,可以将网络更新集成到您的应用程序中,而无需编写复杂的安装和下载脚本。

总结

好的,这真的是我能做到的最简洁的了(说实话!)。其中大多数都可以成为关于这个主题的几篇文章。

每个应用程序都应该内置一些基本的维护功能。现在的用户希望应用程序能为他们处理大部分这些杂务。添加一些诸如自动备份和干净关闭检测之类的功能,将大大有助于向用户表明您关心他们使用您的产品取得长期成功。

© . All rights reserved.