Northwind 数据库与 NoSQL DBreeze





5.00/5 (3投票s)
在 SQL Northwind 数据库上使用 NoSQL DBreeze 数据库与 ASP.NET。
引言
这是一篇关于在 ASP.NET 中使用 NoSQL 的小文章(也是我的第一篇文章),发布在 CodeProject 上。NoSQL 已经存在很长时间了,许多人成功地使用了 NoSQL。我发现关于在 ASP.NET 中使用 NoSQL 的代码和完整示例非常少。每个 NoSQL 数据库都提供了插图和示例,但仅限于入门级别。因此,我将我的整个经过测试的项目作为一篇文章,献给那些对 NoSQL 感兴趣并具有 ASP.NET 背景的人。
可以在学习前下载整个源代码,但必须具备 ASP.NET、C#、Lambda 表达式、N-Tier、泛型、JQuery、JavaScript、KnockoutJs 和 CSS 的经验。当然,还必须使用过 SQL Server 并理解基本的 Northwind 数据库,这个数据库已经存在了 15 年。运行完整代码的唯一要求是 Visual Studio 2010 或更高版本。
背景
关于 NoSQL 的一点介绍。如果你是 NoSQL 的新手,那么 NoSQL 将与传统的 RDBMS 关系型数据库有所不同。所以,首先只需将其视为一个没有关系(意味着没有 RDBMS),因此没有连接约束的数据库。只有实体和一组内部(或依赖)实体,直接保存到磁盘或内存中可管理的文件。如果数据库在磁盘上,它可以直接位于同一工作项目、托管环境或云上。简单地说,有关详细信息,我建议在网上搜索 NoSQL。:-)
本文我将使用 DBreeze NoSQL 嵌入式数据库。如果你下载了源代码,你会发现 DBreeze 二进制文件已经包含在内。如果你想了解更多详细信息,可以直接在网上搜索 DBreeze 并访问他们的主页。
我想,背景介绍得差不多了,现在我们开始借助源代码详细讲解。
Using the Code
只需下载源代码并将其解压到系统上你喜欢的位置。在 Visual Studio 2010 或更高版本中打开项目。
运行前我们需要做一些小的设置,因此首先打开名为 "Site" 的网站的 web.config 文件。在配置文件开头搜索以下行。
<configSections> <section name="logger" type="Logger.Configuration.LoggerConfiguration, Logger"> <section name="dbreezedbconfig" type="DataLayer.DataBaseConfig.DBreezeConfiguration, DataLayer"> <configSections> <logger name="mylogger"> <logconfig folder="sitelog" file="log.txt" filesize="5" rollday="true"><logconfig> <logger> <dbreezedbconfig name="databaseconfig"> <dbreezeconfig databasefolder="App_Data\northwind_db" usebackup="true" backupfolder="I:\NoSql\NorthWind" backupinterval="60"><dbreezeconfig> <dbreezedbconfig>
我简单解释一下,第一部分是日志记录器,这是我创建的自定义日志记录器,其详细信息在 configSections 下的 logger 标签中。
- “folder” 属性将是直接在网站根目录下创建的日志文件夹。
- “file” 属性是日志文件的名称。
- “filesize” 属性是日志文件的大小,这里是 5 GB。达到此大小后,会自动创建另一个文件。
- “rollday” 属性是每天更改文件的属性。
整个 Logger 代码包含在源代码中的“Logger”类库下。现在是第二个配置部分,这对于我们使用 DBreeze NoSQL 数据库很重要。详细信息如下:
- “databasefolder” 属性指定了我们的数据库将存储在哪里。通常我们将其保存在网站应用程序的 App_Data 文件夹中,因此这里也使用了相同的模式。
- “usebackup” 属性指定是否要自动备份 DBreeze 数据库。这里我们使用备份。
- “backupfolder” 属性指定备份需要保存在哪里。请注意,这应该是您系统上的物理位置或共享位置,并且必须赋予 IIS 指定的权限。如果我们在步骤 2 中指定使用备份,则此属性是必需的,否则当然会出错。如果指定的文件夹未找到,也会出错。
- “backupinterval” 属性指定何时进行下一次备份。该数字以分钟为单位,这里是 60,表示每小时需要进行一次备份。(请注意,DBreeze 会按照我们设置的间隔自动备份数据库。)就是这样,如果上述所有配置设置都正确,现在是编译解决方案的时候了,将启动项目设置为我们的网站应用程序,并将起始页设置为 index.html,在 Visual Studio 中按 F5,然后一切就绪了。
有人会想,当你第一次运行应用程序时,会发生什么?让我简单说明一下工作原理。
打开 Global.asax 文件
- 在 Application Start 事件中,有两行代码执行初始设置。
- 第一行调用 DBreeze 数据库引擎,当然在应用程序结束时会释放引擎。
- 第二行使用 DBreeze 创建 northwind 数据库,该数据库在 App_Data 文件夹中创建。只需转到 Business.BaseDataBase 类库,整个脚本都在那里编码。此脚本仅在未找到最需要的基础表时运行一次,这意味着我们是第一次运行。
数据库创建后,整个应用程序开始连接并与我们的数据库交互。请注意,由于我们使用的是嵌入式数据库,数据库的所有文件现在都被锁定。因此,我们每小时会创建一个备份,以便如果需要,我们可以复制实时数据库并开始调查。
关注点
整个解决方案包含工作项目。在详细介绍 NoSQL 之前,让我先阐明项目的基础结构以便于理解。打开解决方案,它将如下图所示。
- Business.Entities 类库包含所有实体。这将进一步用作 NoSQL 的表。NoSQL 没有像 SQL Server 中那样的表。
- DataLayer 类库包含我们的 DBreeze 数据库的存储库类以及使 Dbreeze 运行所需的其他配置元素。存储库用于查询数据库以获取相关数据。由于我们已经在 web.config 中完成了数据库配置,因此配置的基类位于 DataLayer 类库中。
- Business.Components 类库包含所有我们需要实现的业务逻辑。
- NWSTS 类库有一个简单的 Factory 类,这样我们就可以封装所有在另一端不需要的数据。
- Service 类库包含由我们的 Web 应用程序使用的 Web 服务。
- Logger 类库包含用于记录错误或任何其他信息的代码。
- Business.BaseDataBase 类库包含 NoSQL 脚本,该脚本仅在 northwind 数据库未创建时使用一次。
在所有类库中,我们都必须引用 DBreeze DLL。
现在,让我们看看 DBreeze 提供了什么。以下是一些需要理解的要点:
- DBreeze 是一款 NoSQL 嵌入式数据库,它使用一个类作为表。我们在类中定义的任何属性都被视为表的列。
- DBreeze 易于维护数据库引擎以进行事务提交和回滚,因此操作是 ACID 类似的并且完全可管理。
- DBreeze 需要为数据库中每个表中的每一行提供一个唯一键。因此,传统上在 SQL Server 中我们有主键,DBreeze NoSQL 也是相同的概念。唯一的区别是我们需要 System.Collections.Generics.Dictionary 而不是 System.Collections.Generics.List。因此,主键可以保存在类中,也可以保存在 System.Collections.Generics.Dictionary 的键中。
- DBreeze NoSQL 引擎需要在应用程序的整个生命周期中启动一次,然后进行处置。因此,我们可以从 global.asax 文件启动它,或者我们可以为此编写自定义 Windows 服务,然后公开引擎。(我没有尝试过 Windows 服务,但由于我们可以在 .NET 中编写自定义 Windows 服务,因此这可以很容易实现。)
- DBreeze 提供事务,因此传统的提交和回滚使得它对于 SQL Server 用户非常熟悉。有一个简单的经验法则,如果在事务中数据未提交,数据将简单地保存在内存中。
- DBreeze 事务提供同步表功能,因此我们可以显式同步表。这使得与其他表交互的其他线程等待,直到第一个完成。
- DBreeze 事务还提供整个表的排他锁和共享锁。
- DBreeze 最吸引人的特性(我最喜欢)是它无需安装,即插即用,所有后续操作都是完全可管理且是 .NET 的托管代码。我们只需引用 DBreeze DLL 即可。
等等,也有一些缺点,让我们也考虑一下。
- 如上文第 3 点所述,我们需要为每一行设置一个键,而键可以是 .Net 中除 GUID 之外的任何有效数据类型。如果我们需要使用 GUID,这会使 GUID 覆盖 ToString()。
- 我们需要对 DBreeze 引擎采取预防措施,因为它只能初始化和处置一次。因此,我们要么需要一遍又一遍地打开引擎并使用 using 关键字同时处置,要么我们需要全局打开或关闭它。(后者在我们的源代码项目中使用)
请注意,我发现了以上几点,也许会有新的版本发布,或者我可能错过了一些要点。但它们都基于我对 DBreeze 的经验。
让我们看看 DBreeze NoSQL 插入和检索数据的基本用法
using DBreeze;
public class myClass
{
public string id {get;set;}
public string name{get;set;}
}
myClass _myClass = new myClass(){id="1",name="name"};
using (var engine = new DBreezeEngine(@"D:\temp\DBR1"))
{
using (var tran = engine.GetTransaction())
{
try
{
tran.Insert<int, DbMJSON<myClass>>("t1", 1, _myClass);
tran.commit();
}
catch (Exception ex)
{
tran.rollback();
}
}
using (var engine = new DBreezeEngine(@"D:\temp\DBR1"))
{
using (var tran = engine.GetTransaction())
{
try
{
myClass _myClass = Tran.SelectForward<int, DbMJSON<myClass>>("t1").Select(qr=>qr.Value.Get).Where(qr=>qr.name == "name").FirstOrDefault();
}
catch(Exception ex)
{
//log error
}
}
}
如上所示,在表中插入和检索数据非常简单。但是更新呢?DBreeze 没有更新!不要感到惊讶,忘记 SQL Server 吧,这是 NoSQL。对于更新,使用相同的插入操作,如果主键已经在数据库中存在,则更新该记录,如果不存在,则插入。从而最大限度地减少错误。
上述代码在我们的项目中以存储库的形式实现,因此我们不必每次都记住表的结构。我们需要一些泛型经验(开头已说明),如果具备,DataLayer 类库就不需要进一步解释了。泛型仅用于支持上述代码,当然是以泛型的方式。此外,它还包含共享和排他场景的事务类型。我们可以根据业务逻辑需求使用。
我需要提及的最后一点是订单搜索功能。如果你运行应用程序,你会从主屏幕找到订单搜索,点击它并尝试搜索任何订单。你会发现搜索有点慢!为什么?因为我已经在 NoSQL 中实现了 SQL Server,这会产生差异,NoSQL 的结构不应与 SQL Server 的结构和架构相同。我创建这个项目是为了理解 SQL Server 和 NoSQL 之间架构差异。所以让我们简单谈谈这一点。
首先,在 SQL Server 中存在关系。如果熟悉 NorthWind 数据库,我们知道其中
- 订单依赖于订单详情、客户、员工和发货人。
- 此外,订单详情依赖于产品。
- 产品依赖于供应商和类别。
请在 NorthWind 数据库中验证这一点。因此,在创建订单和订单详情之前,我们需要客户、员工、发货人、供应商和产品。当然,依赖关系都在主表上。因此,只需要引用即可。
那么 NoSQL 场景会是怎样的呢?同样地,我们仍然需要主表,但这不再是强制约束。为什么?因为每一个细节都将只添加到 Orders 实体中。我们可以直接映射创建订单的员工、客户、产品,以及发货人和供应商!简单。我们不需要先完成主表再操作依赖表,我们只需当场创建主表并进行关联,即订单实体。
这就是为什么在我们的应用程序中订单搜索很慢的原因,我们坚持了 SQL Server 的架构,这样做是为了我们更好地理解。此外,在 OrderSearch (在 Buisness.Components.Components, 命名空间中) 中,大量使用了 Linq 表达式来创建动态 lambda 表达式。查看一下该类,是的,当然需要了解泛型、Linq 表达式和 Lambda。但在 NoSQL 架构中,情况并非如此。那会非常简单。
客户端还有一个额外的库是 KnockoutJs。它用于轻松地将实体列表与 HTML 和 CSS 绑定。如果你是 KnockoutJs 的新手,只需在 Knockout 官方网站上学习一个简短的教程即可。这些教程简单明了,易于实现。
我想这篇文章到此为止了。说了很多。我期待您对本文的评论,如果我有所遗漏或采用了其他实现方式,欢迎您的建议。此外,我对网页应用程序中实现的糟糕网页设计表示歉意。
谢谢。