Over a million developers have joined DZone.

Triggers in a .NET NoSQL Database

DZone's Guide to

Triggers in a .NET NoSQL Database

Take a look at how triggers work in NosDB, an open source NoSQL database. Learn how you can organize your document changes to hinge on certain phases of the process.

· Database Zone ·
Free Resource

Download "Why Your MySQL Needs Redis" and discover how to extend your current MySQL or relational database to a Redis database.

We know for a fact that one of the greatest things about a NoSQL database is the complete flexibility it provides developers. You do not have to pre-define anything in a collection; neither the columns nor the data-types.

This sounds awesome, but some fear the power of so much flexibility. And rightly so, if your NoSQL database is being accessed by different types of applications. In this case, it is possible that the data being entered does not follow any set of rules to ensure data format consistency, increasing the possibility of human errors just waiting to happen.

You’ve heard the phrase “with great power comes great responsibility.”  With a NoSQL database, I’ve talked with developers who do not want great data power, rather they want tools to reduce, or at least to corral, the infinite flexibility of their data so they are not responsible for every possible data combination. What I mean is that even though the data is unstructured and flexible, methods to exert some control over the data format are welcomed.

So, how to ensure that each and every sub-system of your whole infrastructure is adhering to some basic set of rules or constraints that you as an architect have decided? Ensuring this in every application is just not practical. So instead, NosDB, an open source .NET NoSQL Document Database, provides developers with triggers in C#. In concept, these triggers work exactly the same way as any relational database triggers. The possible triggers available to register are:

  • Pre Insert.
  • Pre Delete.
  • Pre Update.
  • Post Insert.
  • Post Update.
  • Post Delete.

Triggers are functions registered against a database operation. They are executed in response to the operation being performed, hence ‘triggering’ the function. They are triggered whenever a data element is updated, added or deleted allowing the .NET developer to write down data constraints. Once again, because the triggers are written in .NET, they run inside the process of the NosDB database without adding any performance overhead.

So enough of talk and let’s get our hands dirty and test it with code.

Understanding NoSQL Database Triggers

The IDatabaseTrigger interface exists in the namespace of Alachisoft.NosDB.Common.Triggers. As you can easily guess, your application needs to refer to the NosDB Common library to use it. Next, if you either implement or see the interface itself, you will see there are two methods

  • PreTrigger.
  • PostTrigger.

To understand what these do you first need to understand that triggers work when there is a data change about to happen or once it has happened. ‘Data changes’ means operations that include data addition, update, or deletion. Whenever any of these three operations is about to be performed on the collection, the PreTrigger is called. Similarly, when the operation has been performed the PostTrigger is executed.

For our case, we'll only be considering the PreTrigger method because we just want our data to be well structured. It isn't much to wish for.

When you look at the PreTrigger method of the IDatabaseTrigger interface, you'll see you get a TriggerContext as an argument that holds two important pieces of information. One is why the trigger executed, and the second is the type of data we are working with.


So, if you're working with the Northwind database and want to check that each and every order entry should adhere to the following rules:

  • Valid RequiredDate should exist.
  • Valid CustomerID should exist.
  • Valid EmployeeID should exist.
  • Valid ShipperID should exist.
  • Insert Orderdate as DateTime.Now if it does not exist or is NULL.
  • The other part of JSON is to remain flexible.

First, implement the IDatabaseTrigger. For an example, take a look at the following code:

    public class Validation : IDatabaseTrigger

        // After document changes
        public void PostTrigger(TriggerContext context)
            // PostInsert
            // PostUpdate
            // PostDelete

        // Before document changes
        public bool PreTrigger(TriggerContext context)
            IJSONDocument document = context.EventDocument;

            // Operation type
            switch (context.TriggerAction)
                case TriggerAction.PreInsert:

                    if (!document.Contains("RequiredDate") ||
                        !document.Contains("CustomerID") ||
                        !document.Contains("EmployeeID") ||
                        !document.Contains("ShipperID") ||
                        document["RequiredDate"] == null ||
                        document["RequiredDate"].ToString().Length == 0)
                        // Oops! Basic data requirements are missing
                        return false;

                    if (!document.Contains("OrderDate") ||
                        document["OrderDate"] == null ||
                        document["OrderDate"].ToString().Length == 0)
                        // Update JSON Document
                        document["OrderDate"] = DateTime.Now;
                case TriggerAction.PreDelete:
                    // Insert code here 
                case TriggerAction.PreUpdate:
                    // Insert code here
            return true;

In the above code, only three types of TriggerActions are expected. For this example, we are only interested in TriggerAction.PreInsert that is, whenever a new document is about to be inserted we need to check if the data is valid or not.

Now to register the trigger, simply go to the NosDB Management Studio and select the collection you want to work with. Expand the tree and add the trigger by right clicking on CLR Triggers and follow the wizard.

Image title

Now try adding two order objects into the Orders collection. Let one of them be empty, which will be rejected by the trigger, whereas let the other Order object be filled with data, except for the OrderedDate, which will automatically be set to the insertion time.

    // Connection String
    string conn = "Data Source=<YOUR IP>; Port=9950; Database=northwind; Local Instance=false; Integrated Security=true;";

    // Initialize Database
    Database db = NosDB.InitializeDatabase(conn);
    Collection<Orders> ordersCollection = db.GetCollection<Orders>("orders");

    Orders orders = new Orders();

    //Adding an EMPTY Order
    catch (OperationFailedException ex)

    //Adding an Order WITHOUT OrderDate
    orders.ShipperID = 1;
    orders.CustomerID = 1;
    orders.EmployeeID = 1;
    orders.ShippedDate = DateTime.Now;
    orders.RequiredDate = DateTime.Now;

    catch (OperationFailedException ex)


To verify, simply query the orders database and check the new orders added. The empty order will be rejected whereas if only the OrderDate is missing then the inserted document will be updated with DateTime.Now before being inserted in the collection.

Now you can breathe easily with the thought that new versions, or different applications within your architecture, will adhere to some standards of data.

NosDB is a 100% native Open Source .NET NoSQL Database (released under the Apache 2.0 License). NosDB is uber fast and linearly scalable, allowing your .NET applications to handle extreme transaction loads (XTP), and it works in Visual Studio.

NosDB also helps you accelerate .NET development by providing a flexible JSON schema. With JSON, you can quickly adjust to your changing data requirements, thereby lowering your time to market.

Read "Developing Apps Using Active-Active Redis Enterprise" and discover the advantages over other active-actve databases.

nosql c-sharp ,nosql databases

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}