2. Persistent Classes

In this tutorial, you will create a persistent class and make your first database operation using Gazel.

To complete this tutorial download previous solution from here or jump to the previous tutorial.

Create A Persistent Class

Database operations are done using Persistent objects.

An object is Persistent if its class injects its own repository. For more information see: Data Persistence

Create a new class named Task under TaskManagement module.

Add following code to your Task source file.

public class Task { private readonly IRepository<Task> repository; protected Task() { } public Task(IRepository<Task> repository) { this.repository = repository; } } public class Tasks : Query<Task> { public Tasks(IModuleContext context) : base(context) { } }

Task objects will represent each row in Task table.

Tasks class is registered to IoC as a singleton by convention and it will consist of queries to that table. In this tutorial you will not write any queries. Leave this class empty for now.

Task class, by injecting its own repository, indicates that its a persistent class.

  • Notice that both classes are subject to dependency injection.
  • protected Task() { } constructor is there for NHibernate to be able to create proxies on persistent classes for lazy loading.

Now you can add properties to your Task class as shown below;

public class Task { ... public virtual int Id { get; protected set; } public virtual string Name { get; protected set; } public virtual bool Completed { get; protected set; } } ...

First property is mandatory for all persistent classes. Gazel requires an integer Id column for every table.

  • The reason for properties to have a protected setter is to make sure that only Task class can assign values to them. In the next tutorial you will understand why this is important.
  • virtual keywords are there for NHibernate to be able to create proxies on persistent classes for lazy loading.

These properties are automatically mapped to columns of Task table in gazel.tutorial.db database.

Note that you don't have to create tables and columns in your SQLite database. When in local development mode, Gazel configures NHibernate's SQLite connection to automatically create database schema.

Now add following method to Task class.

public class Task { ... protected internal virtual Task With(string name) { Name = name; Completed = false; repository.Insert(this); return this; } } ...

For persistent classes construction is in two steps. First step is the actual constructor, and second step is With methods which takes instance arguments and inserts a row to database via repository.

You may ask why a construction method is named as With instead of something like Create or Insert. Here's why;

Go to TaskManager class in TaskManagement module and add below code to this class.

public class TaskManager { private readonly IModuleContext context; public TaskManager(IModuleContext context) { this.context = context; } public Task CreateTask(string name) { return context.New<Task>().With(name); } }

You may remove SayHello method from previous tutorial.

As you can see you've created a business service named CreateTask which inserts a new task record with the given name. Here you can see how a With method is used. As mentioned above, construction is done in two steps.

  1. The first one is context.New<Task>() which initiates a new Task object using IoC container,
  2. And the second one is .With(name) which inserts a new record using its own repository. So together it's like saying "create a new task with name".

IModuleContext is a gateway to abstraction layer of Gazel. Through this object you can access IoC, File System etc. For more information see: IModuleContext

Now run AppHost.Service project to see your new service Create Task and create tasks using it.

Note that Id's are assigned from database. This is the default mapping configuration Gazel applies to NHibernate.

Testing Persistent Objects

Go to TaskTest class in UnitTest add following test case;

[TestFixture] public class TaskTest : TestBase { [Test] public void CreateTask__creates_a_task_using_given_name() { var taskManager = Context.Get<TaskManager>(); BeginTest(); var actual = taskManager.CreateTask("Write Tests"); Verify.ObjectIsPersisted(actual); Assert.AreEqual("Write Tests", actual.Name); } }

You may remove SayHello__says_hello test case from previous tutorial.

Here is what this test does;

  • Gets TaskManager instance from context: arrange
  • Creates a task named "Write Tests": act
  • Verifies that the Task object is persisted and its name is "Write Tests": assert

  • BeginTest() call prepares underlying mechanism for the execution of service under test.
  • Verify property comes from TestBase class. It basically helps you to check if object is persisted or deleted
  • When testing, Gazel configures a mock service application in which there is a database connection to an in-memory SQLite database. For every test case, it begins a transaction and rollbacks it after test case execution.

Summary

Like manager classes, persistent classes also follow conventions. In this tutorial you've created a table and a create service using no configuration.

Now try to add new properties to Task class or add new persistent classes, re-run and see the results.

Once you are ready, you can proceed to next page to learn how to update a record in database.


You can download complete source code for this tutorial here