Creating a Domain entity
Domain entities provide a way to add your own tables to the Smartstore database. In this tutorial, you will add a simple notification system to your Hello World module.
Preparing the table
Table schema
A simple notification might have the following properties:
A unique identifier (
Id
, type: number)An author, represented by the customer ID (
AuthorId
, type: number)A timestamp (
Published
, type: date-time)A message (
Message
, type: string)
Here is what the table might look like:
1
543
2022-12-12 11:48:08.9937258
Hello World!
2
481
2022-12-13 19:02:55.7695421
What a beautiful day it is 😄
Create the Domain entity
Overview
The domain object is an abstract data structure that has all the properties of the entity it describes. Entity Framework automates the mapping between domain objects and database tables.
Specify the table name and the indexes using Code First Data Annotations and add the properties that represent your database columns.
// Outside the class.
// Specify your table name. By convention, the entity name is used.
[Table("TableNameInDatabase")]
// Declare an index.
[Index(nameof(PropertyName), Name = "IX_ClassName_PropertyName")]
// Inside the class.
// Define some columns.
public int ColumnA { get; set; }
public bool ColumnB { get; set; } = true;
Implementation
Add the Notification.cs file to the new Domain directory and do the following
Specify the table name
Notification
.Declare
AuthorId
andPublished
as indexes.Implement the abstract
BaseEntity
class.Add the
AuthorId
,Published
andMessage
properties.
Your Notification
class should look something like this:
[Table("Notification")]
[Index(nameof(AuthorId), Name = "IX_Notification_AuthorId")]
[Index(nameof(Published), Name = "IX_Notification_Published")]
public class Notification : BaseEntity
{
public int AuthorId { get; set; }
public DateTime Published { get; set; }
[MaxLength]
public string Message { get; set; }
}
This represents the Notification
table with the three columns: AuthorId
, Published
and Message
. The MaxLength
attribute will truncate Message
to the maximum supported length of strings allowed in a property. Because you will often search for notifications based on either AuthorId
or Published
, these are defined as indexes.
Create the Migration
To add the Notification
table to the Smartstore database, you must create a migration. The migration framework creates the table at application startup. In this tutorial, you will only override the Up
method of the abstract MigrationBase
class.
Create the Migrations directory and add the migration class whose name includes the current date, YYYYMMDDHHMMSS_Initial.cs. Add the following attribute to each class
// Use the current date and time [YYYY-MM-DD HH:MM:SS]
[MigrationVersion("2022-12-14 10:34:22", "HelloWorld: Initial")]
The class must inherit from the Migration
base class to have access to the SQL database schema helper methods such as Create
, Remove
, or Update
. You can now use these methods to check if the table already exists, and if it does not, to create it.
var tableName = "Notification";
if (!Schema.Table(tableName).Exists())
{
Create.Table(tableName);
}
To add columns, set indexes, and specify primary keys, you can simply chain the following FluentMigrator methods:
WithColumn
Defines a new column.
WithIdColumn
Defines an id column that will act as the primary key.
You can define a column type (Boolean, Integer, String, Date, Currency, etc.) and declare it as (not) nullable, unique, a primary key, indexed, etc.
Create.Table(tableName)
.WithIdColumn()
.WithColumn(nameof(Notification.AuthorId))
.AsInt32()
.NotNullable()
.Indexed("IX_Notification_AuthorId")
.WithColumn(nameof(Notification.Published))
.AsDateTime2()
.NotNullable()
.Indexed("IX_Notification_Published")
.WithColumn(nameof(Notification.Message))
.AsMaxString()
.NotNullable();
The class should look like this:
[MigrationVersion("2022-12-14 10:34:22", "HelloWorld: Initial")]
public class _20221214103422_Initial : Migration
{
public override void Up()
{
// The table name is taken from Domain->Attribute->Table
var tableName = "Notification";
if (!Schema.Table(tableName).Exists())
{
Create.Table(tableName)
.WithIdColumn() // Adds the Id property as the primary key.
.WithColumn(nameof(Notification.AuthorId))
.AsInt32()
.NotNullable()
.Indexed("IX_Notification_AuthorId")
.WithColumn(nameof(Notification.Published))
.AsDateTime2()
.NotNullable()
.Indexed("IX_Notification_Published")
.WithColumn(nameof(Notification.Message))
.AsMaxString()
.NotNullable();
}
}
public override void Down()
{
// Ignore this for now.
}
}
Providing table access in modules
Now that you have the table set up, you need to give your module access to it. To access the table from a SmartDbContext
instance you need to add the following two files:
Startup.cs in the root of your directory
SmartDbContextExtensions.cs in the Extensions directory (must be created)
Create the static SmartDbContextExtension
class and add the following method:
public static DbSet<Notification> Notifications(this SmartDbContext db)
=> db.Set<Notification>();
The Startup class inherits from the StarterBase
class and contains the following lines:
public override void ConfigureServices(IServiceCollection services, IApplicationContext appContext)
{
services.AddTransient<IDbContextConfigurationSource<SmartDbContext>, SmartDbContextConfigurer>();
}
private class SmartDbContextConfigurer : IDbContextConfigurationSource<SmartDbContext>
{
public void Configure(IServiceProvider services, DbContextOptionsBuilder builder)
{
builder.UseDbFactory(b =>
{
b.AddModelAssembly(GetType().Assembly);
});
}
}
Now you can access the entities stored in your table using the SmartDbContext
.
var messages = await _db.Notifications()
.Where(x => x.Message.Length > 0)
.FirstOrDefaultAsync();
Next steps
The following steps are included in the module code:
Add a configuration view. Configure the number of days to display a notification.
Display the notification as a widget. This way, you can place it anywhere you want in the store.
Add a new notification button. Let the current admin create a message.
Schedule a task to purge the table. This will increase database speed by removing old, unnecessary messages from your table.
Further ideas
There are many other things you can do with this module:
Add a Moderator
CustomerRole
and a separate view to allow certain users to create notifications.Add categories to your notifications. Display specific notifications on different pages.
Make your entities accessible through the Web API.
Conclusion
In this tutorial, you learned how to:
Adding a Table to the Smartstore Database
Create a migration for it
Extend
SmartDbContext
with your tables
Last updated
Was this helpful?