-
-
Notifications
You must be signed in to change notification settings - Fork 200
Tutorial
The purpose the this tutorial is to understand how to save some custom objects to the documents store, create some indexes and execute some queries. This assumes you have some good knowledge of C# and are familiar with document databases concepts.
The full source of the tutorial can be found in the source code in the samples directory.
The model which will be used during this tutorial is made of a single class BlogPost. Here is the complete class:
public class BlogPost
{
public string Title { get; set; }
public string Author { get; set; }
public string Content { get; set; }
public DateTime PublishedUtc { get; set; }
public string[] Tags { get; set; }
}
This class contains different content types in order to demonstrate that we don't have to care about them during the modeling process. There is no constraint on them. As a document, it's a root aggregate, which means any related object will be persisted as only one document. In YesSql a document will be materialized as a single database record in the Document table.
A store is just a simple relational database instance. It can be any type of SQL database, as long as NHibernate supports it. The tutorial will use Microsoft Sql Ce 4.0 but you can switch it to anyone you want.
A store is represented by the Store class. An instance of Store should be unique per application, a singleton. This is a common practice in database management. If you have ever used NHibernate or Entity Framework the you will find it familiar. It depends on each application to define what strategy is used to access this singleton (DI, static accessor, ...). This tutorial is based on single method call, which means it won't deal with this particular aspect.
var store = new Store().Configure(MsSqlCeConfiguration.MsSqlCe40.ConnectionString("Data Source=Store.sdf"));
In this example the store is initialized using a connection string to a local Sql Ce database named Store.sdf.
The store will behave as a factory for database transactions. In YesSql they are called sessions. This is the same terminology as in NHibernate.
// creating a blog post
var post = new BlogPost
{
Title = "Hello YesSql",
Author = "Bill",
Content = "Hello",
PublishedUtc = DateTime.UtcNow,
Tags = new[] {"Hello", "YesSql"}
};
// saving the post to the database
using(var session = store.CreateSession())
{
session.Save(post);
session.Commit();
}
A call to session.Commit() is mandatory in order to commit the transaction. Otherwise the changes would not be taken into account. This is a key principle in YesSql to provide transaction commits.
Now that a document has been saved in the store, we might need to retrieve it. It can be done in various ways which will all be explored, but the simplest one is to load a document by its type only.
// loading a single blog post
using(var session = store.CreateSession())
{
var p = session.QueryDocument<BlogPost>(query => query.FirstOrDefault());
Console.WriteLine(p.Title); // > Hello YesSql
}
Using the QueryDocument method doesn't give access to the inner properties of the documents themselves, which is a major limitations for most real scenarios. To do such queries, you will need to create some dedicated indexes.
In YesSql queries are executed on materialized views called indexes. There are two types of indexes:
- Mapped indexes, to do elementary queries on document properties
- Reduced indexes, for grouping and doing queries on aggregated property values
A mapped index is represented as a class inheriting from HasDocumentIndex. Here is an example which will store the Author property of the BlogPost class.
public class BlogPostByAuthor : HasDocumentIndex
{
public virtual string Author { get; set; }
public override void Describe(DescribeContext context)
{
// for each BlogPost, create a BlogPostByAuthor index
context.For<BlogPost, BlogPostByAuthor>().Index(
map: blogPosts => blogPosts.Select(
p => new BlogPostByAuthor {Author = p.Author})
);
}
}
First, this class as a property Author which will be the author of the blog post. Then there is a Describe method which is used to create an index entry for each BlogPost instance passed to it. Those entries will be save in the database as records with an identifier, a foreign key to the Document table and an Author column.