
Eloquera 4
Short description of the base
From the very beginning, the Eloquera database was written to store objects based on the .Net Framework, which made it possible to try to incorporate all the best from object and relational databases at the same time, overcoming many of their differences. Theoretically, Eloquera can work with any languages from the .Net Framework family, but in practice, work has been tested so far only with C #. The main focus of developers on the enterprise segment (100+ GB), and not on embedded solutions, although the latter are also not deprived of attention.
Distinctive features of Eloquera are very impressive and constantly updated, here is a very short list of them:
- Saves C # objects (any objects of any language on the .Net platform) without the need for special interfaces and adapters.
- Saves Dynamic objects with any fields \ properties and can map them to objects of any type.
- The query language is as close to SQL as possible, and it does not require the presence of any relational SQL database. Plus LINQ support.
- Returns objects in the form in which they were stored (including enumerated types)
- Support for parameters in the form of lists and arrays
- Regular expressions in queries.
- Support for template objects.
- Restore Read-only fields and properties.
- Partial return of objects is supported. For example, if you need the ForumTopic class, then you can not pull up all the links to ForumMessages.
- You can specify the depth of the object to return in the request.
- Stored procedures.
Installation
You can pick up the base distributions from the official website www.eloquera.com after registration. A choice of archives will be presented for desktop installation and for installation as a service (x86 or x64). When installing Eloquera as a service, there are no pitfalls.
Installation on any more or less modern machine will take no more than 5 minutes. Then at your disposal will be:
- Eloquera Config Studio;
- Eloquera DB Studio;
- The service itself is responsible for the operation of the base.
The desktop version is installed on an x-copy basis, i.e. you just need to copy the files to the desired directory. To work, you will need the installed .Net 4 Full Framework.
With this approach, the NuGet package looks quite expected, but at the moment this is not yet available. However, developers are aware of this possibility and are threatening to create one soon, as soon as for the standalone version of the database the kernel will be issued in the form of a library, not an executable file.
Base Modes
Eloquera database can work in several modes:
- A common database for multiple applications, standard mode.
- In-memory mode.
- Desktop - the mode of the base built into the application.
Code for connecting to the server and creating the database:
private const string DBName = "ServiceDatabase";
using (var eloquera = new DB("server=localhost:43962;options=none;")) {
eloquera.CreateDatabase(DBName);
eloquera.OpenDatabase(DBName);
eloquera.Close();
}
The DB class is used to connect to the database . The connection constructor is passed to the class constructor; in this example, the connection goes to the service.
Eloquera supports in-memory mode both when working as a service, and when working offline (desktop mode). In the free version, the memory base can take up to 1 GB. It is also worth remembering the physical availability of RAM, since it is possible that the size of the database is such that Windows will try to place it in the swap file on disk. As you know, this does not add speed at all.
In order to indicate to the engine that we want to create a database in RAM, you will need to specify a special parameter inmemory in the connection string.
new DB("server=(local); options=inmemory;"))
In this case, the database will exist only in RAM, however, an empty file will still be created in the file system . In order to be able to resume work with such a database, you must use the persist parameter in the connection string in the options.
For working in desktop mode, the connection string will be like this:
new DB("server=(local); options=none;"))
In order for Eloquera to start working in Desktop mode, you need to stop the EloqueraDB service, otherwise you will receive an error saying that it is impossible to connect to the service at the address (local).
A lot of interesting things in the database, but I will dwell on the most interesting probably.
Joins
The general syntax for an operation is:
SELECT Alias1,Alias2 FROM Type1 Alias1 [ LEFT | RIGHT| INNER | FULL ] JOIN Type2 Alias2 ONSomeFunction(Alias1.Field1, Alias2.Field2)
If two different types or more were used in building a query using JOIN in SELECT, the result of such an operation will be a new IEnumerable
JOIN requests, like other types of requests, can use named parameters. Including the expression ON. However, there are some limitations to keep in mind:
- The value of the parameter must be determined before the query starts.
- Named parameters cannot be used to replace type names in a Select statement. Those. an attempt to call Select type will be out of rules.
Separately, it is worth mentioning how the issue is solved with the descendants of the classes involved in the construction of the JOIN expression. The standard behavior is the ability to use inherited types in a query. For example, if TypeC is inherited from TypeA, then the expression:
SELECT a, b FROM TypeA a INNER JOIN TypeB b ON b.id = a.id
can return objects of type TypeC in the "a" field if they satisfy the conditions of the expression. In order to get rid of all descendants of the class in the query results, use the word ONLY. Those. rewrite the request like this:
SELECT a, b FROM ONLY TypeA a INNER JOIN TypeB b ON b.id = a.id
Now in the field “a” there will be only objects of type TypeA.
An example in pictures on the work of Inner Join. Suppose we have such a data structure: We are faced with the task of finding all schools and jobs located in one place. The code:

var queryResult = (IEnumerable>)
db.ExecuteQuery("SELECT sch, wp FROM School sch INNER JOIN WorkPlace wp ONch.Location=wp.Location");
The results in the form of a table can be represented as follows:
# | queryResult [“sch”] | queryResult [“wp"] |
1 | School1 | wPlace2 |
2 | School2 | wPlace2 |
3 | School3 | wPlace3 |
4 | School3 | wPlace4 |
Parameters
Parameters can only be used to transfer data to the request, so it is useless to fantasize about receiving data through parameters.
Using parameters is very simple:
Parameters param = db.CreateParameters();
param["name"] = "John"
To use the parameter in the request, you must use the overloaded method that accepts them. For instance:
var res = db.ExecuteQuery("SELECT BasicUser WHERE Name = @name", param);
An array of parameter values can be interpreted by the database as a simple array:
Parameters param = db.CreateParameters();
param.AddList("emails", new string[]{"john@gmail.com", "david@hotmail.com"});
var res = db.ExecuteQuery("SELECT BasicUser WHERE ALL @emails in Emails", param);
Parameters can be used with Top, Skip and Order By. Parameters may also contain null.
Stored procedures
Starting with version 4.0, Eloquera supports stored procedures.
Stored procedures can be considered as extension methods to the main database. They are written using C #, for which I thank the creators for not inventing any of their interpreted dialect for this matter. It turns out that you can use all the .Net feature when writing procedures.
So, enough words, it’s better to show how stored procedures are actually created.
The first step is to declare an interface with the desired procedures. This interface must be on the client and server side.
public interface ICityStatisticSP{
CityCars GetCityCars(string cityName);
}
Then we create a class that will be needed only on the server side. In this case, the library with the implementation of the procedure must be placed in the Lib folder in the database directory, or the path to the libraries with stored procedures must be configured using the StoredProceduresPath parameter .
public class CityStatisticSP: StoredProcedure, ICityStatisticSP {
public CityCars GetCityCars(string cityName) {
Parameters parms = db.CreateParameters();
parms["city"] = cityName;
var cars = db.ExecuteQuery("SELECT Car FROM Car JOIN Seller ON Car.SellerID = Seller.ID WHERE Seller.City = @city", parms)
.OfType()
.ToList();
…
}
}
Adding new procedures does not require a restart of the database service.
After you have thrown the library with the procedures to the server, you can call the procedure on the client using the following code:
ICityStatisticSP procedures = db.GetStoredProcedureClass();
string cityName = "Chicago";
CityCars cars = procedures.GetCityCars(cityName);
Based on the very object nature of the database, you do not need to configure the mapping configuration procedure and other things-other-things for the procedure.
The presence of stored procedures in their existing form solves more complex problems than simply saving and recalling database queries. It is worth emphasizing that all code is executed on the base side. Those. using procedures, you can greatly reduce the load on the network, when using procedures you can more effectively filter data on the server side, by filtering, for example, create new elements and save them in the database. I think that it is not difficult to imagine a situation when you need to add a number of elements from the database with some value. With the old approach, you would have to unload all the elements, create a selection according to the conditions for updating, update, and overtake new data over the network back. A stored procedure will solve such problems much more efficiently.
Dynamic Objects (Dynamic)
According to the Eloquera developers, they added some magic to the object base and got unique functionality and an object, which they called Dynamic. You have already guessed where the legs grow from this feature, and with what it is ideologically coordinated in C #. Dynamic objects can be stored in themselves as structured data, i.e. classes and structures defined by you in C # code, and arbitrarily composed. Moreover, you can freely represent these objects in the form of each other.
The main advantage is the ability to add and remove fields from the saved object - the data is magically attached and embedded into the object.
Benefits that dynamic objects provide:
- They are easy to create and use. No need to worry about missing fields and properties. Any number of fields of any type can be added to runtime.
- They automatically determine the type of field and work with it in accordance with its capabilities and limitations. Dynamic objects fully support indexing.
- They can refer to each other and be contained in each other.
- Dynamic objects are very, very fast.
- They can be converted on the fly to "native" objects and vice versa .
- For work, a data scheme is not required, which gives a very wide field for activity.
- Blog engines, CMS, wiki
- User Profiles and Registration
- Storing Record History
- Cases when data needs to be filtered or aggregated in runtime.
- Applications that operate with variables by the number of attributes of different types.
Regarding the last two points, it should be clarified that we mean various programs that allow users to independently construct data types, dynamically compose an interface for each user. There is no rational possibility to store such data in a strict form without explosive complexity. Using Dynamic allows you to describe such types in infinite variety and work with them in a single style.
Another example is web 2.0, where users can add comments to everything, associate materials, and so on. With traditional relational databases, a hard description of classes, such schemes are impossible or very difficult to implement.
A quick overview of working with dynamic objects
The structure of dynamic objects can be modified at any time along with the data contained. Together with ease of use, this provides more than ample opportunity for data evolution.
Dynamic @do = new Dynamic();
@do["Title"] = "Some title";
@do["Price"] = 14.99;
@do["DateAdded"] = DateTime.Now;
db.Store(@do);
Dynamic res = (from Dynamic d in db where d["Price"] == 14.99 select d).First();
The same is possible with variables of type dynamic introduced in .Net 4.
dynamic @do = new Dynamic();
@do.Title = "Some title";
@do.Price = 14.99;
@do.DateAdded = DateTime.Now;
db.Store(@do);
dynamic res = (from Dynamic d in db where d["Price"] == 14.99 select d).First();
Please note that when using LINQ, you must use d [“Price”] to explicitly indicate the construction of the expression tree.
When working with dynamic objects, it is possible to find out all the fields that an object contains:
Dynamic @do = dynamics[0];
foreach (var field in @do) {
Console.WriteLine(String.Format("Field Name {0} Value {1} Type {2}", field.Key, field.Value, field.Type));
}
In addition to wide possibilities, there are some limitations, in particular, there is a list of characters that cannot be used when specifying field names. This is to avoid collisions while writing SQL queries to objects. Here is a list of reserved characters:
.,%] [+ - $! * ()
I hope that you will be interested in the base and at least take the base as a note for home experiments.
I can organize a series of articles if it is interesting, there is ready material.