使用MVC4,Ninject,EF,Moq,构建一个真实的应用电子商务SportsStore(三)
上篇中我们已经展示数据到View, 但是这些数据都是来自于我们的mock IProductRepository,在我们真正的实现repository之前,我们需要创建一个SQL Server数据库并添加一些数据。
我们将使用EF框架操作SQL Server数据库, EF是一个.net ORM框架,ORM框架能让我们想操作对象实例一样操作数据库的表、列、行。就像使用正常的C#对象,这么做需要一点Linq的知识,Linq不是什么神秘的、高难的东西,相信所有人都能够在想当短的时间内掌握并使用LInq。
点击View菜单,打开服务器资源管理器,点击连接到数据库。你会看到连接对话框,设置服务器名为(localdb)\v11.0,这是一个特殊的名字,表示你要使用本地数据库的特性。VS2012新添加了一个特性,就是可以使用SQL Server的内核创建一个免管理员的本地数据库,相关的详细使用说明,请参见相关文档,这里就不细说了。现在,请确保你选择了windows认证登陆方式,设置数据库名为SportsStore。如下图:
点击确定,然后会出现确认对话框,点击yes,就会创建一个新的数据库。
我们现在只有一个Product表,右击表文件夹,选择添加新表:
创建新表可以有2种方式,这里我们使用T-SQL方式,因为它更精准,更方便,建表语句如下:
CREATE TABLE Products
(
[ProductID] INT NOT NULL PRIMARY KEY IDENTITY,[Name] NVARCHAR(100) NOT NULL,[Description] NVARCHAR(500) NOT NULL,[Category] NVARCHAR(50) NOT NULL,[Price] DECIMAL(16, 2) NOT NULL
)
这个表与我们之前定义的Product model 类略有不同,现在点击更新按钮,你会看到一个更新的Summary
如下:
点击更新数据库按钮。表就会被创建出来,我们需要添加些数据到这个表中。
创建Entity Framework Context
最新版的EF包含了一个很不错的特性,叫做code-first,意思是我们能在我们的model中定义一些类,然后
从这些类生成数据库。在此,我不想去谈论这种技术的优缺点。相反,我将基于这个code-first,展示给你一个变体,我们将整合我们的model类和一个存在的数据库,现在我们先安装EF框架到我们的项目。
打开NuGet工具包管理程序,安装EF框架,如下图:
现在,在SportsStore.Domain工程中创建一个文件夹,叫做Concrete,然后添加一个文件,命名为EFDbContext,代码如下:
using SportsStore.Domain.Entities;
using System.Data.Entity;
namespace SportsStore.Domain.Concrete
{
public class EFDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
}
}
为了使用code-first特性的优势,我们需要创建一个类,它派生自 System.Data.Entity.DbContext. 这个类会为数据库中的每个表自动定义一个属性,并指定表名为属性名,我们现在的属性名是Products,并且类型参数是Product. 我们希望Product model被用作展示 Products表中的行。现在我们要告诉Entity Framework怎样去连接数据库,所以我们要添加一个连接字符串到SportsStore.WebUI工程的Web.config文件中。
<connectionStrings>
<add name="EFDbContext" connectionString="Data Source=(localdb)\v11.0;Initial
Catalog=SportsStore;Integrated Security=True"
providerName="System.Data.SqlClient"/>
</connectionStrings>
创建Product Repository
现在,我们要为实现真是的数据操作添加一个文件到 Concrete文件夹中,叫做EFProductRepository。编辑这个文件,看起来像下面的样子:
using SportsStore.Domain.Abstract;
using SportsStore.Domain.Entities;
using System.Linq;
namespace SportsStore.Domain.Concrete {
public class EFProductRepository : IProductsRepository {
private EFDbContext context = new EFDbContext();public IQueryable<Product> Products {
get { return context.Products; }
}
}
}
这个repository 类实现了 IProductRepository接口并使用一个EFDbContext 实例去数据库中取数据。你将看到EF是怎么样 工作的。现在我们需要编辑NinjectControllerFactory类,用真正的数据替换Mock 对象。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using SportsStore.Domain.Abstract;
using SportsStore.Domain.Entities;
using Moq;
using Ninject;
using SportsStore.Domain.Concrete;
namespace SportsStore.WebUI.Infrastructure
{
public class NinjectControllerFactory: DefaultControllerFactory
{
private IKernel ninjectKernel;
public NinjectControllerFactory() {
ninjectKernel = new StandardKernel();
AddBindings();
}
protected override IController GetControllerInstance(RequestContext
requestContext, Type controllerType) {
return controllerType == null ? null : (IController)ninjectKernel.Get(controllerType);
}
private void AddBindings() {
Mock<IProductsRepository> mock = new Mock<IProductsRepository>();
//mock.Setup(m => m.Products).Returns(new List<Product> {
// new Product { Name = "Football", Price = 25 },
// new Product { Name = "Surf board", Price = 179 },
// new Product { Name = "Running shoes", Price = 95 }
//}.AsQueryable());
//ninjectKernel.Bind<IProductsRepository>().ToConstant(mock.Object);
ninjectKernel.Bind<IProductsRepository>().To<EFProductRepository>();
}
}
}
运行你的项目,你将看到如下画面:
下一篇中,我们将添加更多商品,并应用分页技术,让用户能够浏览我们商品,并可以从一个页面移动到另一个页面,我们也将逐步的加入购物车等功能,为您一步一步地展开这个项目,如果您喜欢它,请继续关注我的续篇!
王志岳
塔塔信息技术(中国)股份有限公司 | 开发者导航