A Sample eCommerce Site With Entity Framework and nopCommerce
Using the code-first approach of the Entity Framework with the open source nopCommerce tool to create an eCommerce website.
Join the DZone community and get the full member experience.
Join For Freeentity framework (ef) is an object relational mapper (orm) that enables developers to work with relational data using domain-specific objects. in other words, it allows developers to access and store data in the database via an automated mechanism. before we dive deep into the details of code-first approach, we should understand the transference in a way the modern applications are being developed.
conventionally, we have been developing data centric applications where the focus is what data is needed to justify our business needs. hence, the traditional approach in most cases is always about building the application based on the database schema. many developers still follow this approach and the approach is commonly known as “entity framework database first approach”. in this approach, the entity framework is created from an existing database.
on the other hand, many developers are shifting towards the alternative way of developing (and designing) applications by using domain centric approach (domain-driven design).
what is domain-driven design (ddd)? ddd is a collection of principles and patterns that help developers craft elegant object systems. properly applied it can lead to software abstractions called domain models. these models encapsulate complex business logic, closing the gap between business reality and code. (source: msdn )
this approach is basically an opposite of data-driven approach and the focus is entities and models which is why it is known as “entity framework code first approach”. as the name implies, the classes are created first and then database is generated from the classes to fulfill the business needs. in this approach, we do not use entity designer (.edmx). this approach enables us to write plain-old" clr objects (pocos) for our models and it helps in making changes to the persistence layer without impacting the models.
what is poco? the entity framework enables you to use custom data classes together with your data model without making any modifications to the data classes themselves. this means that you can use "plain-old" clr objects (poco), such as existing domain objects, with your data model. these poco data classes (also known as persistence-ignorant objects), which are mapped to entities that are defined in a data model, support most of the same query, insert, update, and delete behaviors as entity types that are generated by the entity data model tools. (source: msdn )
here is a graphical representation of entity framework's code-first approach that helps developers in easily creating classes as the requirement and database is created automatically.
let’s create a sample web application in asp.net mvc that uses entity framework (code-first approach). in this example, we are going to create a test e-commerce store with a product table that we can add, edit, and delete.
create a new c# web project:
let’s name this sample project “efcodefirstmvcapplication”:
in the new project dialog box, we will select mvc template and click on the “change authentication” button:
in the “change authentication” dialog box, we will select “no authentication” and click ok:
here is the sample project in solution explorer:
now, we run the solution, we should see the sample web application in the browser like this:
installing entity framework
now, we need to install entity framework to your project and in order to do so, go to: package manager console.
enter the following command: install-package entityframework
nuget will automatically install the latest version of entity framework (in this example, ef 6.1.3 is being installed as this is the most recent version).
data model
now, we will create entity classes for the test e-commerce store application. in order to keep it simple, let’s create just one entity “product” where we will maintain the product inventory / stock.
in the “models” folder, create a new class file as “product.cs” and use the following code:
using system;
using system.collections.generic;
using system.linq;
using system.web;
namespace efcodefirstmvcproductsapp.models
{
public class product
{
public int id { get; set; }
public string prod_sku { get; set; }
public string prod_name { get; set; }
public datetime createdate { get; set; }
}
}
here, the id property will become the primary key column of the database table for the respective class (product). by default, entity framework reads the property names as id or classid as the primary key.
database content (data access layer)
the database content class is the main class that coordinates entity framework functionality for a given data model. add a new folder “dal” which will be our data access layer:
now, we will add a new class file named as “productcontext.cs” with the following code:
using system;
using system.collections.generic;
using system.linq;
using system.web;
using efcodefirstmvcproductsapp.models;
using system.data.entity;
using system.data.entity.modelconfiguration.conventions;
namespace efcodefirstmvcproductsapp.dal
{
public class productcontext : dbcontext
{
public productcontext()
: base("productcontext")
{
}
public dbset<product> products { get; set; }
protected override void onmodelcreating(dbmodelbuilder modelbuilder)
{
modelbuilder.conventions.remove<pluralizingtablenameconvention>();
}
}
}
in the above code, this is our connection string:
public productcontext()
: base("productcontext")
{
}
now we can initialize the database with some test / sample data by creating a new class file “productinitializer.cs” in the dal folder and use the following code:
using system;
using system.collections.generic;
using system.linq;
using system.web;
using efcodefirstmvcproductsapp.models;
using system.data.entity;
namespace efcodefirstmvcproductsapp.dal
{
public class productinitializer : system.data.entity.dropcreatedatabaseifmodelchanges<productcontext>
{
protected override void seed(productcontext context)
{
var products = new list<product>
{
new product{prod_name="hp laptop",prod_sku="hp101",createdate=datetime.parse("2016-01-01")},
new product{prod_name="apple iphone",prod_sku="apple102",createdate=datetime.parse("2016-01-01")},
new product{prod_name="lenovo desktop",prod_sku="lenovo103",createdate=datetime.parse("2016-01-01")},
new product{prod_name="t-shirt",prod_sku="shirt104",createdate=datetime.parse("2016-01-01")},
};
products.foreach(s => context.products.add(s));
context.savechanges();
}
}
}
now, we need to update our web.config file by adding the connection string like this:
<connectionstrings>
<add name="productcontext" connectionstring="data source=workstationpc\sqlexpress2012;initial catalog=efcodefirstmvcapplication;integrated security=sspi;" providername="system.data.sqlclient"/>
</connectionstrings>
in order to tell entity framework to use the initializer class that we have added in the project, an element needs to be added to web.config file like this:
<contexts>
<context type="efcodefirstmvcapplication.dal.productcontext, efcodefirstmvcapplication">
<databaseinitializer type="efcodefirstmvcapplication.dal.productinitializer, efcodefirstmvcapplication" />
</context>
</contexts>
controller and views
now, it is time to create webpage for display data, editing data and deleting data from the database. before, we go forward let’s build the project for making the model and content classes available to the mvc controller scaffolding.
right click on the “controllers” folder and add “new scaffolded item” like this:
in the controller dialog box, click “add” and provide the following information:
-
model class: product (efcodefirstmvcapplication.models)
-
data contect class: productcontext (efcodefirstmvcapplication.dal)
-
controller name: productcontroller
this should automatically add pages for add, edit, details and delete like this:
now, if we run the web application, we should be able to see the product list page by going to: /product
a great example of entity framework code-first approach: nopcommerce
now, that we understand what is entity framework code-first approach and how to perform basic crud (create, read, update & delete) operations. let’s look into an open source ecommerce software which is based on asp.net mvc and follows this approach (project name: nopcommerce ). the code base of nopcommerce follows best practices like inversion of control, separation of concerns, orm, automapping, etc and is always updated with the latest versions of asp.net mvc. nopcommerce offers a ready to use data layer using the newest entity framework with code first and fluent api, both making it very easy to extend.
nopcommerce can be download here: http://www.nopcommerce.com/downloads.aspx
nopcommerce is also available in microsoft web app gallery: https://www.microsoft.com/web/gallery/nopcommerce.aspx/en-us
why developers and designers should choose nopcommerce?
-
can be easily modified and in lesser time compared to other competitive cart solutions because its architecture is very well defined, is predictable.
-
it is the only well featured shopping cart in asp.net mvc framework.
-
dependency management via autofac, which integrates both with mvc and your custom code.
-
an extensible plugin architecture that works without touching the core.
-
a built-in user management with all the required features like two-away authentication, password recovery, openid and most importantly acl (access control list) allowing for fine-grained permissions management.
-
an extensible theming mechanism.
-
great quality plugins and themes. more than 1,000 plugins and themes available for ready usage.
so, why nopcommerce follows the code-first approach? what are the benefits that nopcommerce project gets by following entity framework code first approach?
speedy development: code-first approach allows the nopcommerce development to be faster and much more efficient because it updated the database automatically when the model is changed. so, developers do not have to worry about creating a database which means no manual database intervention is required.
control on database versions: in a code-first approach, the database schema is completely based on the code models so it helps in controlling the versions of the database. this way, nopcommerce development team can easily maintain (and release) the increment versions as versioning databases is quite effective in this approach.
poco: this allows nopcommerce code to be much more cleaner and the developers do not have to deal with a lot of auto-generated code.
full control: if developers follow “database-first” approach, they are at the mercy of what is generated from the database. code-first approach allows full control for the model from the source code. it means, nopcommerce developers can easily control every aspect of the code models and the database design.
no edmx/designer: following any existing database to generate .edmx models file results in a lot of auto-generated code. not having to deal with .edmx gives an advantage to nopcommerce developers because it makes source code less bloat and the coded models becomes the database.
let’s look into the nopcommerce source code organization:
\libraries\nop.core the nop.core project contains a set of core classes for nopcommerce, such as caching, events, helpers, and business objects (for example, order and customer entities).
\libraries\nop.data the nop.data project contains a set of classes and functions for reading from and writing to a database or other data store. it helps separate data-access logic from your business objects. nopcommerce uses the entity framework (ef) code-first approach. it allows you to define entities in the source code (all core entities are defined into nop.core project), and then get ef to generate the database from that. that's why it's called code-first. you can then query your objects using linq, which gets translated to sql behind the scenes and executed against the database. nopcommerces use a fluent code api to fully customize the persistence mapping. you can find more about code-first here or here.
\libraries\nop.services this project contains a set of core services, business logic, validations or calculations related with the data, if needed. some people call it business access layer (bal).
projects into \plugins\ solution folder \plugins is a visual studio solution folder that contains plugin projects. physically it's located in the root of your solution. but plugins dlls are automatically copied in \presentation\nop.web\plugins\ directory which is used for already deployed plugins because the build output paths of all plugins are set to "..\..\presentation\nop.web\plugins\{group}.{name}\". this allows plugins to contain some external files, such as static content (css or js files) without having to copy files between projects to be able to run the project.
\presentation\nop.admin nop.admin is an mvc web application project. if you haven't used asp.net mvc before, please find more info here. as you may guess it is a presentation layer for admin area. physically this project is located under \presentation\nop.web\administration directory. this project cannot be run.
\presentation\nop.web nop.web is also an mvc web application project, a presentation layer for public store. this is the application that you actually run. it is the startup project of the application.
\presentation\nop.web.framework nop.web.framework is a class library project containing some common presentation things for both nop.admin and nop.web projects.
\test\nop.core.tests nop.core.tests is the test project for the nop.core project.
\test\nop.data.tests nop.data.tests is the test project for the nop.data project.
\test\nop.services.tests nop.services.tests is the test project for the nop.services project.
\test\nop.tests nop.tests is a class library project containing some common test classes and helpers for other test projects. it does not have any test.
\test\nop.web.mvc.tests nop.web.mvc.tests is the test project for the presentation layer projects.
for more details, you can refer to nopcommerce documentation: http://docs.nopcommerce.com/display/nc/nopcommerce+documentation
adding a new property
let’s try adding a new property (new field) to the “category table” in nopcommerce database. in order to do so, first we need to define the property (field) which can be done in this location:
\libraries\nop.core\domain\catalog\category.cs
open category.cs file and add the property to the category class:
public string newtestproperty { get; set; }
your code should look like something like this:
using system;
using system.collections.generic;
using nop.core.domain.discounts;
using nop.core.domain.localization;
using nop.core.domain.security;
using nop.core.domain.seo;
using nop.core.domain.stores;
namespace nop.core.domain.catalog
{
/// <summary>
/// represents a category
/// </summary>
public partial class category : baseentity, ilocalizedentity, islugsupported, iaclsupported, istoremappingsupported
{
private icollection<discount> _applieddiscounts;
/// <summary>
/// our test property
/// </summary>
public string newtestproperty { get; set; }
/// <summary>
/// gets or sets the name
/// </summary>
public string name { get; set; }
/// <summary>
/// gets or sets the description
/// </summary>
public string description { get; set; }
second steps is to add your new property to the constructor of the categorymap class which is location in this location:
\libraries\nop.data\mapping\catalog\categorymap.cs
add this:
this.property(m => m.newtestproperty).hasmaxlength(255).isoptional();
your categorymap class should look something like this:
using nop.core.domain.catalog;
namespace nop.data.mapping.catalog
{
public partial class categorymap : nopentitytypeconfiguration<category>
{
public categorymap()
{
this.totable("category");
this.haskey(c => c.id);
this.property(c => c.name).isrequired().hasmaxlength(400);
this.property(c => c.metakeywords).hasmaxlength(400);
this.property(c => c.metatitle).hasmaxlength(400);
this.property(c => c.priceranges).hasmaxlength(400);
this.property(c => c.pagesizeoptions).hasmaxlength(200);
//our test property
this.property(m => m.newtestproperty).hasmaxlength(255).isoptional();
}
}
}
now, we if run the project and re-install the database, we should be able to see the new property in the category table (in nopcommerce database).
here is a screenshot of the nopcommerce database that includes the new property that we just added.
this shows that how easy it is to add new properties in nopcommerce database by following entity framework code-first approach. as we have learned in the above article (tutorial) the classes are created first and then database is generated from the classes to fulfill the business needs. nopcommerce is a great example that follows this approach and helps developers in customizing the solution easily as per the requirement(s) or business needs.
-
nopcommerce can be download here: http://www.nopcommerce.com/downloads.aspx
-
nopcommerce version (used in this article): version 3.70
-
nopcommerce support: http://www.nopcommerce.com/boards/
Published at DZone with permission of Lavish Kumar. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments