[Architecture] — Creating a Singleton In-memory database in .NET
To provide an easy starting point for stories in the future, I created this in-memory data store that can either be built from scratch or forked from Github. I implemented a thread-safe singleton design pattern from Refactoring Guru (Singleton (refactoring.guru)) to allow this to be used with asynchronous, multi-threaded applications with a rudimentary level of data integrity protection.
Our goal is to create a database capable of managing students and courses. We will develop this with SOLID principles and dependency inject our SingletonRepository at the end of the article. Here’s how we do this:
Folder Structure
We’ll start by defining a DataLayer folder where all our code will live, then create three folders in it. Like so:
Models
Next, we’ll define our objects to be managed and stored by this singleton repository.
We’ll start with the Course repository. Add the course
class to the Models folder and add the appropriate tests in a separate project.
Next, create the student
class in the Models folder and add its tests in the StudentTests.cs
file.
With our models created, we can start defining our interfaces.
Interfaces
We’ll start by defining an IObjectRepository<T>
generic interface that defines a CRUD interface for an object T
. Interfaces do not need to be tested and are generally boilerplate code:
Next, we’ll define two interfaces ICourseRepository
and IStudentRepository
that inherit from the IObjectRepository
. Like so:
And then:
With our interfaces defined, we have to create our singleton repositories that implement these interfaces and implement the singleton pattern.
Repositories
Implementing the singleton repositories is the most complex and most well-tested aspect of our codeunit. To save time, I will embed the test classes for testing our repositories without explaining the test purpose. I’ll have to ask you, the reader, to trust me when I say that the tests verify each repository function and ensures that only one instance of our singleton can be created in multi-threaded environments.
We’ll stary by creating a CourseSingletonRepository.cs
class that implements the ICourseRepository
interface and add a private constructor (preventing the use of the ‘new
‘ command). Next, we’ll create an initialization function called GetSingleton()
that creates a single instance of our class during the lifetime of our application. Once we’ve verified that this code works, we’ll implement our repository CRUD methods and run tests on them. The code for the course repository is as follows:
The student singleton repository code is implemented similarly. However, we have a few more methods to be implemented from the IStudentRepository
interface. It should look like this:
And the tests for those classes are as follows:
Conclusion
With this, we’ve got a functioning singleton repository that we can use in later projects! Happy coding!
Here is a repository containing the finished singleton repository and its classes: BelugaDiver/.NET-starting-point: Creates a thread-safe singleton in-memory database that manages students and courses. (github.com)