In the last post about the LOB Gamification Service, the explanation of the video is a great starting point for defining the domain model I will be using.
"Every time the user crossed a lightning bolt Action, the user receives some points toward a Proficiency. A single Action might give points to multiple Proficiencies. A single Proficiency can earn points through various Actions. Proficiencies have different Levels. As users earn points within a Proficiency, the user "levels up" that Proficiency. Leveling up typically gives badges and other rewards."
The words in bold are candidates for objects in the domain model. Wikipedia defines Domain Model as "The domain model is created in order to represent the vocabulary and key concepts of the problem domain. The domain model also identifies the relationships among all the entities within the scope of the problem domain, and commonly identifies their attributes."
The following class diagram is my working version of the LOB Gamification Domain Model. I anticipate having to change the model up as the finer details of the gamification service expose themselves during implementation. My only hope is I don’t look back and not recognize this first working version.
LOB Gamification Administration Website Domain Model
Entity | Description |
Application | Entity that represents a LOB application. Each Application contains a list of Proficiencies, Users and Actions. |
Proficiency | A skill or technique used in the LOB application that the gamification system will reward users for performing actions related to. |
Administrator | The account manager responsible for defining what Proficiencies, Actions and Users will be gamified within an application. |
Action | Something done or performed by a user in the LOB application that gives the user points to one or more Proficiencies. |
User | A person or system that performs actions in the LOB application. |
ProficiencyLevel | Each Proficiency can be broken into multiple levels to represent different tiers of skills. |
UserAction | Entity that captures the transaction of a user performing an action. |
UserProficiency | Entity that summarizes the proficiency level of a user. |
ProficiencyAction | Entity that captures what actions give points to what Proficiencies. |
What I want to do is create a website that allows an Administrator to log in, define an Application and add the Proficiencies, Actions and Users that will be gamified within that application. The actual gamification service is not the subject of this blog series but just the creation of the administration website to support the service.
Create the Visual Studio Solution and Projects
I created a solution with 4 projects as demonstrated by John Papa in his course "Single Page Apps with HTML5, Web API, Knockout and jQuery" and in his blog series "Building Single Page Apps with Knockout, jQuery, and Web API – Part 1 – The Story Begins" found here.
First, I created a new MVC4 project and called it LobGame.Web
:
The administration website will be an internet site.
My solution looked like this:
I added 3 additional projects to the solution with the following references:
Project Name | Visual Studio Project Template | Purpose | References |
Lob.Game.Web | | | Lob.Game.ModelLob.Data.ContractsLob.DataEntityFramework |
Lob.Game.Model | C# Class Library | Domain Model Classes | |
Lob.Data | C# Class Library | Classes that retrieve data from the database | Lob.Game.ModelLob.Data.ContractsEntityFrameworkSystem.Data.Entity |
Lob.Data.Contracts | C# Class Library | Interfaces of classes that retrieve data from the database | |
To add a reference to Entity Framework, I recommend using NuGet.
- Project –> Manage Nuget Packages
- Select the "Online" tab
- Select the "
EntityFramework
" package - Click "Install"
My solution now looked like this:
Create the Model
Looking at the domain model class diagram, let’s start small and simple. For now, I just defined the top 2 classes in the object graph which are "Application
" and "Administrator
". I added these 2 classes to the LobGame.Model
project.
Create the Context
Entity Framework Code First
I have used Entity Framework for several production products but I have yet to use the Code First feature. What I have found is that many examples on the web use EF Code First. My lack of knowledge in EF Code First was hurting my ability to stay current. I studied up and I now have a working knowledge. Let me demonstrate how magical EF Code First can be.
EF Code First is built around the DBContext class. MSDN defines the DBContext
as "Represents a combination of the Unit-Of-Work and Repository patterns and enables you to query a database and group together changes that will then be written back to the store as a unit. DbContext
is conceptually similar to ObjectContext."
The simplest way to start using the classes for data access is to define a context that derives from System.Data.Entity.DbContext
and exposes a typed DbSet<TEntity>
for each class in the domain model.
In the LobGame.Data
project, I added a derived context called LobGameDbContext
with a DbSet
for both Application
and Administrator
.
To my initial surprise, this is all the code needed to get and save data from a database. Obviously, there is quite a bit going on behind the scenes and we’ll take a look at that in a moment, but first let’s see it in action.
In the LobGame.Web
project, in the "Global.asax.cs" file, I put the following code in "Application_Start
".
Running the application at this point, EF Code First creates a database based upon the 2 model classes we defined for Administrator
and Application
. Here is a screenshot of my SQL Management Studio after running the application.
Magical eh? A database out of nowhere. By default, EF Code First will create the database in SQL Express. The name of the database is the name of the DBContext
class. EF Code First used the DbSet<Administrator> Administrators
property of the LobGameDbContext
class to name the "Administrators
" table. It used the public
properties of the Administrator
class to define the columns. Notice the Name
field is set to nvarchar(max)
.
Similarly, a table for Applications was created. EF Code First was also smart enough to look at the class properties to derive the proper many to many PK/FK relationships in the form of the ApplicationAdministrator
table. That is pretty amazing if you ask me.
Saving Data
The DbContext
class has an internal class called Database
that has a method called "SetInitializer
". Whenever the database is created, you can use this to seed the database with data which is a great way to demonstrate how the Model
classes can be used to save data.
In the LobGame.Data
project, I created a folder called SampleData and put the following LobGameDatabaseInitializer
class in it.
The Seed
method will be called whenever there is a change to the Model
. This code is pretty standard, simply creating some new instances of Application
and Administrator
and adding them to DbContext
followed by calling SaveChanges()
.
I have to tell the LobGameDbContext
to use this initializer.
If you delete the database and rerun the application, you will notice now that Administrators
table has data as shown here.
Perhaps you want to control the name of the database. All we need to do is define a new ConnectionString
in the Web.Config of LobGame.Web
.
Then, we need to tell LobGameDbContext
to use the "LobGame
" connection string.
Running the example now and checking Management Studio, there is a new database with the name "LobGame
" which was pulled from the new connection string.
Suppose we wanted to limit the name of the Application Name field to 50 characters. I will demonstrate how to do this with the Fluent API of Code First. I added a "Configuration" folder inside of the LobGame.Data
project. I added the "ApplicationConfiguration
" class shown here:
Again, I needed to tell LobGameDbContext
to use the ApplicationConfiguration
.
DbContext
has a method that you can override whenever it is creating the model called "OnModelCreating
". Here, I told it to use ApplicationConfiguration
. I also told DbContext
to not pluralize the table names. If you run the application now, you will see the differences.
Notice the nvarchar(50)
instead of nvarchar(max)
. Notice the singular table names. The EF Code First Fluent API is very powerful. For more details, I recommend the following link. I feel the most efficient learning was by watching Julie Lerman "Entity Framework 4.1 – Code First" Pluralsight course.
At the end of this post, I have a link to the source code which has the remaining domain model classes defined. I recommend looking at the code, particularly the "Configuration" folder for more Fluent API examples.
We have made pretty good progress in this blog post. We have a solution with multiple projects. One of the projects contains the domain model and another project contains the ability to read/write the domain model to a SQL Server database. In the next blog post, I will detail how we can create the Web API that surfaces the data to a browser.