Domain
Entities and O/R Mapping
Overview
The domain tier contains all entity classes that are mapped to database tables. Some of the most used classes are:
An entity class is a "Plain old CLR object" (POCO). It usually represents one database table, with each property typically representing one column in the table.
BaseEntity
A concrete entity class must derive from the abstract class BaseEntity. By convention:
BaseEntity.Id
is used as the primary key.All public properties with a getter and a setter will be included in the database schema.
To customize the default mapping conventions:
Use the DataAnnotation attributes on classes and properties.
Write Fluent API mapping code.
It may seem a bit cluttered at first glance, but it is good practice to keep entity class and Fluent API mapping in a single code file.
For performance reasons, Smartstore does not use proxy classes for lazy loading, but the ILazyLoader
interface instead. Therefore, a protected LazyLoader
property that allows lazy loading of navigation properties is declared in the BaseEntity
class. You don't need to inject the ILazyLoader
service, the property is automatically injected when an entity is attached to the context. If an entity is loaded without being tracked, or if it is manually detached from the context, the NullLazyLoader
- which does nothing - will be injected instead.
Lazy loader usage example:
public class MyEntity : BaseEntity
{
// 1:1 navigation property
private Product _product;
public Product Product
{
// The "LazyLoader" property is declared in the "BaseEntity" class
get => _product ?? LazyLoader?.Load(this, ref _product);
set => _product = value;
}
// 1:n navigation property
private ICollection<Category> _categories;
public ICollection<Category> Categories
{
// The "LazyLoader" property is declared in "BaseEntity" class
get => LazyLoader?.Load(this, ref _categories) ?? (_categories ??= new HashSet<Category>());
// "protected" --> prevent assignment
protected set => _categories = value;
}
}
Domain assemblies
On app start-up Smartstore scans all application core assemblies for entity types. If you created a new entity class and want to make it accessible, there are different approaches depending on the project type.
In a core project simply extend the partial SmartDbContext
class.
public partial class SmartDbContext
{
public DbSet<MyEntity> MyEntities { get; set; }
}
In a module project you need to inform Entity Framework that your module assembly contains entity types to pickup and register on start-up.
For this you need a starter class.
internal class Startup : StarterBase
{
public override void ConfigureServices(IServiceCollection services, IApplicationContext appContext)
{
services.AddTransient<IDbContextConfigurationSource<SmartDbContext>, SmartDbContextConfigurer>();
}
class SmartDbContextConfigurer : IDbContextConfigurationSource<SmartDbContext>
{
public void Configure(IServiceProvider services, DbContextOptionsBuilder builder)
{
builder.UseDbFactory(b =>
{
b.AddModelAssembly(this.GetType().Assembly);
});
}
}
}
For more comfort while developing you can add this extension:
public static class SmartDbContextExtensions
{
public static DbSet<MyEntity> MyEntities(this SmartDbContext db)
=> db.Set<MyEntity>();
}
Entity characteristics
Numerous interfaces can be implemented and some abstract base classes can be derived from to specify what an entity has/is, supports or represents.
The following types declare some properties your entity must implement in order to follow the contract.
Interfaces
IAclRestricted
Has access restrictions
IAttributeAware
Has some raw attributes
IAuditable
Has auditing properties
IDiscountable
Has applicable discounts
IDisplayedEntity
Is displayed somehow in UI
IDisplayOrder
Is orderable
ILocalizedEntity
Is localizable
INamedEntity
Has a conceptual name
IMergedData
Has mergeable data
IPagingOptions
Has data paging options (page size etc.)
IRulesContainer
Is a container for other rules
ISlugSupported
Supports SEO slugs
ISoftDeletable
Is soft deletable
IStoreRestricted
Supports store mapping
ITransient
Supports transiency
Abstract base classes
EntityWithAttributes
Has generic attributes (see Generic attributes)
EntityWithDiscounts
Has applicable discounts
CustomerContent
Represents content entered by customer
Last updated
Was this helpful?