Overall Architecture
In these sections of the nopCommerce Developer Documentation, we will broadly cover the overall architecture of nopCommerce. Detailed descriptions of each component will be described in later sections of the developer guide.
Note that this part is an introductory overview. A more detailed discussion will come later in the guide. Depending on your experience level, these overviews may be enough to get you going!
ORM / DAL
nopCommerce uses SQL Server (various editions) and Entity Framework (EF) as its backing store and ORM. EF is used in code-first mode to perform database creation and object-relational mappings. Data is “materialized” as Plain Old Class Objects (POCO's), as opposed to heavyweight domain objects. The code-first mappings are located in project Nop.Data, folder “Mapping,” and are pretty typical.
// EF code-first mapping excerpted from LibrariesNop.DataMappingCatalogProductMap.cs
public partial class ProductMap : EntityTypeConfiguration<Product>
{
public ProductMap()
{
this.ToTable("Product");
this.HasKey(p => p.Id);
this.Property(p => p.Name).IsRequired().HasMaxLength(400);
this.Property(p => p.Sku).HasMaxLength(400);
this.Property(p => p.Price).HasPrecision(18, 4);
this.Property(p => p.Weight).HasPrecision(18, 4);
this.Property(p => p.Length).HasPrecision(18, 4);
this.Property(p => p.Width).HasPrecision(18, 4);
this.Property(p => p.Height).HasPrecision(18, 4);
this.HasMany(p => p.ProductTags)
.WithMany(pt => pt.Products)
.Map(m => m.ToTable("Product_ProductTag_Mapping"));
}
}
The core DbContext
class is Nop.Data.NopObjectContext
. However it is not a "bag of DbSets
" like you find in many code-first samples. Instead, types are discovered via reflection, and IQueryable
objects are exposed via the repository pattern (Nop.Data.EfRepository<T>
). The repository is in turn consumed by the many service classes (Nop.Services project).
// EF type discovery code from LibrariesNop.DataNopObjectContext.cs
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()
.Where(type => !String.IsNullOrEmpty(type.Namespace))
.Where(type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
foreach (var type in typesToRegister)
{
dynamic configurationInstance = Activator.CreateInstance(type);
modelBuilder.Configurations.Add(configurationInstance);
}
base.OnModelCreating(modelBuilder);
}
As with any large EF project, the context class allows for certain types of “pass-through” queries that bypass the construction of entity queries: In Nop.Data.NopObjectContext
, the pass-through methods are ExecuteStoredProcedureList()
, SqlQuery()
, and ExecuteSqlCommand()
. Mostly they are used for SQL Server Full Text stored procedure calls and maintenance such as truncating and seeding tables.
For more details on... | Refer to the section called... |
---|---|
The ORM/DAL | “Data / ORM / DAL / Custom Data” |
Use of reflection to discover types | “Dependency Injection and Type Discovery” |
Full Text search | “Search” |
Interesting reading
POCOs vs DTOs vs Domain Objects - There are some disagreements as to exact definitions, but a good place to start would be Stackoverflow.com: What is the difference between domain objects, POCOs and entities? and
Rudy Lacovara: What is the Difference Between a DTO and a POCO?
Repository pattern – Two thought-provoking articles by Ayende Rahein about the repository pattern: The evils of the repository abstraction layer and Repository is the new Singleton. A nice discussion about thin repositories and ORMs: Say No to the Repository Pattern in your DAL