RavenDB introduction RavenDB is a NoSQL database developed based on. NET. RavenDBisatransactional, open-sourceDocumentDatabasewrittenin.NET, offeringaflexibledatamodeldesignedtoaddressrequirementscomingfromreal-
RavenDB introduction RavenDB is a NoSQL database developed based on. NET. Below is a simple official introduction: RavenDB is a transactional, open-source Document Database written in. NET, offering a flexible data model designed to address requirements coming from real-
RavenDB Introduction
RavenDB is a NoSQL database developed based on. NET. The following is a simple translation officially introduced:
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 is a transactional open-source document database written in. NET. It provides flexible data models and is designed to meet real-world system requirements.
RavenDB allows you to quickly and efficiently build high-performance, low-latency applications.
For more information, visit the official website: Scenario introduction.
NoSQL is generally used in Web scenarios, such as Web applications (especially MVC Web applications) or Web services (including REST services ). Recently, Hong Kong server Leasing requires a simple data editing tool. For some reason, this tool must be integrated with a desktop Windows Forms Application, it must also meet the needs of multiple users to operate data at the same time. Can NoSQL such as RavenDB be used as a Server-side database for this standard C/S model?
Of course the answer is yes. After all, RavenDB itself supports two operating modes: Embedded mode and Server mode ). For C/S applications, it is natural to deploy RavenDB on a Server, run in Server mode, and then access it through the. NET Client API on the Client.
Problem Encountered
The biggest problem encountered when using RavenDB in this C/S application is the restrictions imposed by some features of RavenDB:
The amount of data obtained each time is limited. RavenDB specifies that the data size obtained each time is 128 by default, and a maximum of 1024 data records can be configured. The amount of data in my tool is about 5000. In fact, if other database technologies (such as Entity Framework) are used, they can be loaded to the memory at one time in the LAN. However, using RavenDB requires paging.
The number of calls per Session is limited. RavenDB specifies that the maximum number of server calls per Session is 30, and it is recommended that the maximum number be controlled once. Due to this rule, a shared session cannot be maintained throughout the lifetime of the client application. This restriction does not exist for EF.
Search is based on Lucene. An error occurs when performing the Contain operation on the string, because RavenDB relies on Lucene for similar full-text searches. Therefore, you need to pre-define the Search index and use a separate Search method.
RavenDB's built-in Lucene word divider has problems with Chinese support. You need to use other Chinese Word divider separately.Solution
Based on the above restrictions and some features of my C/S tool, the following solutions are used:
Combined with BindingNavigator and BindingSource, an automatic paging tool class (RavenDBDataSource) is compiled, which enables the front and back navigation buttons of BindingNavigator to implement paging navigation and supports conditional filtering (Where) and the page after the full-text Search (Search. For specific usage, see "RavenDBDataSource resolution and usage ".
Although a shared Session cannot be maintained, a shared Store object can be maintained, and a separate Session can be created each time data needs to be obtained or updated. However, it should be noted that, because there is no shared Session, it will lead to the tracking of data loss and changes retrieved before, and you need to track and submit it yourself. See "how to save data changes" below ".
From Lucene. NET website downloaded the Contri package and directly used the "Lucene. net. analysis. cn. chineseAnalyzer ", that is, Lucene. net. contrib. analyzers. dll files are stored in the directory RavenDB \ Server \ Analyzers. If you are interested, you can also use Lucene of ICTCLAS.
If the pre-defined full-text search index is used, after connecting to the database, check whether the required index exists. If the index does not exist, use the code to create it. Of course, you can also create it through Studio. See "create Index ".
RavenDBDataSource parsing and usage
See: https://github.com/heavenwing/redmoon/blob/master/RavenDBDataSource.cs for code
This class provides a constructor public RavenDBDataSource (IDocumentStore store, BindingNavigator bn, BindingSource bs), which can take IDocumentStore, BindingNavigator, and BindingSource as parameters. Some bn initialization will be performed.
Provides an overloaded Load method, which can have no parameters or accept Func , IRavenQueryable > Criteria, string indexName =. Criteria is used to construct a query. As the name suggests, you need to input a pre-defined index name during the Search operation. In the Load method, the query constructed by the call code is executed. Paging query is performed based on the PageSize setting. The query result is assigned to BindingSource to prompt the control bound to BindingSource (such as DataGridView). When querying by page, the current page number is also updated.
The TextChanged event processing of the PositionItem of the BindingNavigator object triggers the Load event. To avoid too frequent execution, I used a Custom Event delimizer (see: https://github.com/heavenwing/redmoon/blob/master/DelayEvent.cs) and of course I could also use RX for latency.
The specific usage is simple: instantiate a RavenDBDataSource for a specific object class, then call the Load method to construct a query in the Load method. For example:
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 );}}
In the above Code, multiple attributes can be filtered (Where) at the same time, or one or more attributes can be searched by setting the index name (index1Name ).