NopCommerce Demo Widget -2 Part






4.43/5 (4 votes)
CodeProject Welcome to second post in series of posts: Developing NopCommerce plugin. Till now we already have project ready for working in NopCommerce solution. In prevoius post link we started with creating and preparing project for working in NopCommerce platform.
Welcome to second post in series of posts: Developing NopCommerce plugin.
Till now we already have project ready for working in NopCommerce solution.
In prevoius post link we started with creating and preparing project for working in NopCommerce platform. Project name is Nop.Plugin.Widgets.DemoWidget. This name is standardized and Nop.Plugin.Widgets should be part of project name of every widget type NopCommerce project. Word on end is our project name, in our case DemoWidget.
In this post we will cover data layer. Let’s begin
Our demowidget should be very simple. On public side is a widget with just one drop down list. This drop down list will be populated from database. In admin part will be datagrid and infrastructure to add, edit and delete items for our drop down list datasource. In this post we will see how to add table in database, map domain class to database and prepare our plugin for working with database.
In this post, as first step, we will add new folder Domain
In this folder we will add new class WidgetDemoRecord.cs
This class should inherit class BaseEntity from Nop.Core namespace.
Code in this clas is:
using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; using System.Text; using System.Threading.Tasks; using Nop.Core; namespace Nop.Plugin.Widgets.DemoWidget.Domain { public class WidgetDemoRecord : BaseEntity { public WidgetDemoRecord() { } public virtual int WidgetDemoRecordId { get; set; } //virtual property is for lazy loading user for Entity Framework public virtual string WidgetDemoRecordName { get; set; } } }
Here are two properties. It is pretty self explanatory. List of objects of this class will be used as data source for our drop down list.
WidgetDemoMap should inherit class EntityTypeConfiguration with generic type WidgetDemoRecord which we want to map.This class actually contains metadata how we should map out WidgetDemoRecord class into database.
namespace Nop.Plugin.Widgets.DemoWidget.Data { public class WidgetDemoMap : EntityTypeConfiguration<WidgetDemoRecord> { public WidgetDemoMap() { ToTable("DemoWidget_WidgetDemo"); //Creating table in database with this name HasKey(m => m.WidgetDemoRecordId); // WidgetDemoRecordId is primary key for this class! Property(m => m.WidgetDemoRecordName); // map property to database table } } }
Next, we should prepare for working with database. We will working with Fluent API Entity Framework, rather then with annotation.
We are creating now domain mapping class and adding Entity framework reference to our project.
We should reference dll from nopcommerce directory nopCommerce_3.60_Source\packages\EntityFramework.6.1.3\lib\net45, rather then from nudget as we usually do, to avoid conflicts with NopComerce Entity framework version.
We are adding now new folder in our project DATA and add new class file WidgetDemoMap.cs.
Next we should create ContextObject class who will be in charge for our database operations.
ContextObject class is specialized version of Entity Framework DBContext. It inherits DBCOntext and NopCommerce specific interface IDbContext. NopCommerce framework uses interface IDbContext to find plugin context classes and register at startup. Intention of our ContextObject is to work with standard CRUD database operations and to manage relationship between objects(referential integrity between tables).
In DATA folder we are adding new class WidgetDemoObjectContext
Code in this class is:
public class WidgetDemoObjectContext : DbContext, IDbContext { public WidgetDemoObjectContext(string nameOrConnectionString) : base(nameOrConnectionString) // we can pass name or connection string to tell DbContext to which database shoul be connected { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new WidgetDemoMap()); //we are passing to modelbuilder our WidgetDemoMap to be sure that our plugin has only tables in our modelBuilder and i our case this is just one table WidgetDemoRecord wihich is described WidgetDemoMap class base.OnModelCreating(modelBuilder); } public string CreateDatabaseInstallationScript() { return ((IObjectContextAdapter) this).ObjectContext.CreateDatabaseScript(); //creating sql script for tables defined in OnModelCreating method } public void Install() { Database.SetInitializer<WidgetDemoObjectContext>(null); Database.ExecuteSqlCommand(CreateDatabaseInstallationScript()); SaveChanges(); } public void Uninstall() { this.DropPluginTable("DemoWidget_WidgetDemo"); } public new IDbSet<TEntity> Set<TEntity>() where TEntity : Core.BaseEntity { return base.Set<TEntity>(); } public bool AutoDetectChangesEnabled { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public void Detach(object entity) { throw new NotImplementedException(); } public int ExecuteSqlCommand(string sql, bool doNotEnsureTransaction = false, int? timeout = null, params object[] parameters) { throw new NotImplementedException(); } public IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params object[] parameters) where TEntity : Core.BaseEntity, new() { throw new NotImplementedException(); } public bool ProxyCreationEnabled { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters) { throw new NotImplementedException(); } }
Next thing we should care about is dependency injection. In nopcommerce is used contructor injection . Autofac actually take care about constructor parameters. Autofac instantiates and manage instance lifecycle.
Autofac will know how to create instance based on rules in class DependencyRegistrar. This class we will create in just a moment.
We should not forget, of course to add autofac dll reference.
Actually, we will need two references:
1. Autofac.dll in folder nopCommerce_3.60_Source\packages\Autofac.3.5.2\lib\net40
2.Autofac.Integration.Mvc in folder nopCommerce_3.60_Source\packages\Autofac.Mvc5.3.3.4\lib\net45
Next we will add new class in out Data Folder called DemoWidgetDependencyRegistrar.cs. It is very important for this class to implement interface IDependencyRegistrar
NopCommerce platform will search through reflection classes which implements this interface and will call Register method.
public class DemoWidgetDependencyRegistrar : IDependencyRegistrar { private const string CONTEXT_NAME = "nop_object_context_demo_widget"; public int Order { get { return 1; } // in our plugin order is notimportant, this property actually shows in wich order will be register this method if we have more Regiter mwthod in our plugin } public void Register(Autofac.ContainerBuilder builder, Core.Infrastructure.ITypeFinder typeFinder) { this.RegisterPluginDataContext<WidgetDemoObjectContext>(builder, CONTEXT_NAME); builder.RegisterType<EfRepository<WidgetDemoRecord>>() .As<IRepository<WidgetDemoRecord>>() .WithParameter(ResolvedParameter.ForNamed<IDbContext>(CONTEXT_NAME)) .InstancePerLifetimeScope(); } }
Code above should say something like : Autofac will everytime when in constructor parameter is WidgetDemoRecord, referenced as IRepository in constructor arguments,autofac will bring instead of this parameter new instance of EFRepository. Because EFRepository class in constructor needs parameter IDBCOntext, autofac will instantiate new instance of our WidgetDemoObjectContext class because of CONTEXT_NAME parameter.
InstancePerLifetimeScope means that we will have just on EFrepository instance through on web request which is good. We will not worry that we have more instances of EFrepository class that is WidgetDemoRecord object
We finished data access arhictecure for our plugin. Our plugin in ready to start!
Project download source code link (3.60 NopCommerce version)Nop.Plugin.Widgets.DemoWidget