热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

RavenDB在传统C/S应用下的一点实践

RavenDB介绍RavenDB是一个基于.NET开发的NoSQL数据库。下面是官方介绍的一个简单翻译:RavenDBisatransactional,open-sourceDocumentDatabasewrittenin.NET,offeringaflexibledatamodeldesignedtoaddressrequirementscomingfromreal-

RavenDB介绍 RavenDB是一个基于.NET开发的NoSQL数据库。下面是官方介绍的一个简单翻译: RavenDB is a transactional, open-source Document Database written in .NET, offering a flexible data model designed to address requirements coming from real-

RavenDB介绍

RavenDB是一个基于.NET开发的NoSQL数据库。下面是官方介绍的一个简单翻译:

RavenDB is a transactional, open-source Document Database written in .NET, offering a flexible data model designed to address requirements coming from real-world systems.

RavenDB allows you to build high-performance, low-latency applications quickly and efficiently.

RavenDB是一个用.NET编写的事务性开源文档数据库,提供灵活的数据模型,设计用于解决来自真实世界系统的需求。

RavenDB允许你快速而高效地构建高性能、低延迟的应用程序。

更多介绍可以浏览官方网站的介绍: 场景介绍

由于NoSQL一般是用于Web场景,比如Web应用程序(尤其MVC Web应用程序),或者Web服务(包括REST服务等)。最近,香港服务器租用,需要实现一个简单的数据编辑工具,不过由于某些原因,这个工具必须和一个桌面的Windows Forms应用程序集成在一起,且也要满足多个用户同时操作数据的需求。对于这种标准的C/S模式的应用,能否使用RavenDB这样的NoSQL来作为Server端的数据库呢?

答案当然是可以的。毕竟RavenDB本身就支持两种运行模式:嵌入模式(Embedded)和服务器模式(Server)。对于C/S的应用,很自然就是把RavenDB部署在一个服务器上,运行于Server模式,然后在客户端通过.NET Client API来访问。

遇到问题

在这个C/S应用程序中使用RavenDB的过程中,遇到的最大的问题,还是RavenDB本身的一些特性所带来的限制,分别为:

  • 每次获取的数据量有限制。RavenDB规定每次获取的数据量默认为128条,最多可配置为1024条。对于我这个工具的数据量,就是5000条左右,其实如果使用其他数据库技术的话(比如Entity Framework),且也在局域网内,完全可以一次性载入到内存中。然而使用RavenDB就必须考虑分页处理。
  • 每个Session能够调用的次数有限制。RavenDB规定每个Session调用服务端的最大次数是30,并且推荐最好控制在1次左右。由于有这样的规定,就无法在整个客户端应用程序的生存期内保持一个共享的session。 对于EF也不存在这样的限制。
  • 搜索是基于Lucene的。对于字符串进行Contain操作会出错,这是由于对于类似的全文搜索,RavenDB都是依赖于Lucene的。因而需要预先定义搜索的索引,并使用单独的Search方法。
  • RavenDB内置的Lucene分词器对于中文的支持有问题。就需要单独使用其他中文分词器。
  • 解决方式

    针对以上的限制,并结合我这个C/S小工具的一些特点,使用了如下解决方式:

  • 结合BindingNavigator和BindingSource,编写了一个自动分页的工具类(RavenDBDataSource),可以让BindingNavigator的前后导航按钮实现分页导航,还可以支持条件过滤(Where)和全文搜索(Search)后的分页。具体用法见下“RavenDBDataSource解析和用法”。
  • 虽然不能保持一个共享的Session,但是可以保持一个共享的Store对象,在每次需要获取数据或更新数据的时候,创建单独的Session。不过需要注意的是,由于没有共享Session,会导致之前取回的数据丢失变更跟踪,需要自己进行跟踪与提交。见下面的“如何保存数据变更”。
  • 我从Lucene.NET的网站下载了Contri包,直接使用了里面的“Lucene.Net.Analysis.Cn.ChineseAnalyzer”,即把Lucene.Net.Contrib.Analyzers.dll文件放到RavenDB\Server\Analyzers目录里面。把当然有兴趣的同学也可以使用ICTCLAS的Lucene实现。
  • 预定义全文搜索索引的话,我的方式是在连接数据库后,检查是否存在所需索引,不存在就用代码创建。当然也可以通过Studio来创建。见下”创建索引”。
  • RavenDBDataSource解析和用法

    代码见:https://github.com/heavenwing/redmoon/blob/master/RavenDBDataSource.cs

    这个类提供了一个构造器public RavenDBDataSource(IDocumentStore store, BindingNavigator bn, BindingSource bs),可以接受IDocumentStore 、BindingNavigator 和BindingSource 作为参数。其中会对bn进行一些初始化处理。

    提供了一个重载的Load方法,可以无参数,或者接受Func, IRavenQueryable> criteria, string indexName = ""两个参数。criteria用来对查询进行构造,indexName顾名思义,在进行Search操作的时候就需要传入预先定义的索引的名称。在Load方法中,会对调用代码构造好的查询进行执行,根据PageSize的设置进行分页查询,把查询结果赋值给BindingSource来提示和BindingSource绑定的控件(如DataGridView)进行刷新。在进行分页查询的同时,也会更新当前的页码。

    其中BindingNavigator 对象的PositionItem的TextChanged事件处理,会触发Load事件。为了避免频率过高的执行,我使用了一个自定义的事件延迟器(见:https://github.com/heavenwing/redmoon/blob/master/DelayEvent.cs),当然也可以使用RX来进行延迟。

    具体用法就很简单:实例化一个用于具体实体类的RavenDBDataSource,然后调用Load方法,在Load方法中构造查询。如:

    private void LoadProcessData() { if (_dsProcess == null) _dsProcess = new RavenDBDataSource(_store, bnProcess, bsProcess); var txt = tstbSearchForProcess.Text.ToLower(); if (string.IsNullOrEmpty(txt)) { if (tscbSource.SelectedIndex == 0) { if (tscbRelatedCount.SelectedIndex <5) _dsProcess.Load(query => query .Where(o => o.RelatedCount == tscbRelatedCount.SelectedIndex) .OrderBy(o => o.ProductName)); else _dsProcess.Load(query => query .Where(o => o.RelatedCount >= 5) .OrderBy(o => o.ProductName)); } else { if (tscbRelatedCount.SelectedIndex <5) _dsProcess.Load(query => query .Where(o => o.Source == tscbSource.Text && o.RelatedCount==tscbRelatedCount.SelectedIndex) .OrderBy(o => o.ProductName)); else { _dsProcess.Load(query => query .Where(o => o.Source == tscbSource.Text && o.RelatedCount >= 5) .OrderBy(o => o.ProductName)); } } } else { _dsProcess.Load(query => query .Search(o => o.ProductName, txt) .OrderBy(o => o.ProductName), index1Name ); } }

    上述代码中,可以同时对多个属性进行过滤(Where),也可通过设定索引名称(index1Name)对一个或多个属性进行搜索(Search)。

    推荐阅读
    • 如何用UE4制作2D游戏文档——计算篇
      篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
    • Centos7.6安装Gitlab教程及注意事项
      本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
    • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
    • Java验证码——kaptcha的使用配置及样式
      本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
    • ps:写的第一个,不足之处,欢迎拍砖---只是想用自己的方法一步步去实现一些框架看似高大上的小功能(比如说模型中的toArraytoJsonsetAtt ... [详细]
    • 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之六 || API项目整体搭建 6.1 仓储模式
      代码已上传Github+Gitee,文末有地址  书接上文:前几回文章中,我们花了三天的时间简单了解了下接口文档Swagger框架,已经完全解放了我们的以前的Word说明文档,并且可以在线进行调 ... [详细]
    • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
      本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
    • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
    • 云原生边缘计算之KubeEdge简介及功能特点
      本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
    • 如何去除Win7快捷方式的箭头
      本文介绍了如何去除Win7快捷方式的箭头的方法,通过生成一个透明的ico图标并将其命名为Empty.ico,将图标复制到windows目录下,并导入注册表,即可去除箭头。这样做可以改善默认快捷方式的外观,提升桌面整洁度。 ... [详细]
    • 学习笔记(34):第三阶段4.2.6:SpringCloud Config配置中心的应用与原理第三阶段4.2.6SpringCloud Config配置中心的应用与原理
      立即学习:https:edu.csdn.netcourseplay29983432482?utm_sourceblogtoedu配置中心得核心逻辑springcloudconfi ... [详细]
    • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
    • baresip android编译、运行教程1语音通话
      本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
    • 本文介绍了ASP.NET Core MVC的入门及基础使用教程,根据微软的文档学习,建议阅读英文文档以便更好理解,微软的工具化使用方便且开发速度快。通过vs2017新建项目,可以创建一个基础的ASP.NET网站,也可以实现动态网站开发。ASP.NET MVC框架及其工具简化了开发过程,包括建立业务的数据模型和控制器等步骤。 ... [详细]
    • 使用J2SE模拟MVC模式开发桌面应用程序的工程包的介绍
      以我开发过的一个娱乐管理系统为例:下图为我系统的业务逻辑的MVC流程:下图为以Eclipse开发中各包的说明:转载于:https:blog ... [详细]
    author-avatar
    手机用户2502855763
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有