RavenDB


To use RavenDB database integration, the NuGet package CrystalSharp.RavenDb must be installed.

IMPORTANT

Kindly keep in mind that this particular configuration is intended for the purpose of storing data in the database and reading the data from the database. However, the configuration procedures for the Event Store, Read Model Store, and Sagas will be approached differently.

In order to integrate a database effectively, it is necessary to adhere to the following mandatory steps:

  • An aggregate must be inherited from AggregateRoot<string>. It is mandatory that the <string> type be passed to the base class.
  • Register the implementation of RavenDB.
  • Use IRavenDbContext for database operations.

Following is the code that illustrates how to perform the above steps:

public class Order : AggregateRoot<string>
{
    public string OrderCode { get; private set; }
    public decimal TotalPrice { get; private set; }

    // Rest of the code and logic
}

In the above code snippet, Order aggregate is inherited to AggregateRoot<string>. Here, the Id is of type string, which is why <string> is passed to the base class. It is mandatory to use string for the Id, as the Crystal Sharp framework specifically uses the string type for the Id in RavenDB.

NOTE

If there are any domain event handlers, then those domain event handlers will be triggered only after the data has been successfully stored in the database.

Registration for the RavenDB is required. Following is the code that illustrates how to register RavenDB in the Program.cs file:

RavenDbSettings ravenDbSettings = new("CONNECTION-STRING", "DATABASE-NAME");

CrystalSharpAdapter.New(builder.Services)
    .AddCqrs(typeof(PlaceOrderCommandHandler))
    .AddRavenDb(ravenDbSettings)
    .CreateResolver();

In the above code snippet, when initializing the Crystal Sharp framework, the RavenDbSettings class is instantiated with a connection string and the database name, and then a call to an extension method is made AddRavenDb(ravenDbSettings).

IMPORTANT

It is mandatory to use “IRavenDbContext” for performing database operations.

IRavenDbContext provides the following methods and properties:

IDocumentStore DocumentStore { get; }
IDocumentSession Session { get; }
Task SaveChanges(CancellationToken cancellationToken = default)

IDocumentStore and IDocumentSession are the interfaces of the RavenDB.Client, which is the official NuGet package from RavenDB. The Crystal Sharp framework internally uses the RavenDB.Client package. For loading and querying an entity, the Session property of IRavenDbContext must be utilized.

IMPORTANT

It is important to note that when saving the data in the database, the “SaveChanges” method of “IRavenDbContext” must be used.

Following is the code that illustrates the saving of data:

public class PlaceOrderCommandHandler : CommandHandler<PlaceOrderCommand, PlaceOrderResponse>
{
    private readonly IRavenDbContext _dbContext;

    public PlaceOrderCommandHandler(IRavenDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public override async Task<CommandExecutionResult<PlaceOrderResponse>> Handle(PlaceOrderCommand request, CancellationToken cancellationToken = default)
    {
        Order order = Order.PlaceOrder(request.OrderCode, request.TotalPrice);

        _dbContext.Session.Store(order);

        await _dbContext.SaveChanges(cancellationToken).ConfigureAwait(false);

        PlaceOrderResponse response = new() { OrderId = order.GlobalUId };

        return await Ok(response);
    }
}

In the above code snippet, IRavenDbContext is injected into the command handler constructor, and then in the Handle method of the command handler, a new order is created and saved.