NopCommerce源码架构详解--EF数据访问实例详解

NopCommerce源码架构详解--EF数据访问实例详解

3189发表于2017-05-13

今天我来分析一下nop里面怎么访问数据库,我们知道Nop里面的ORM是使用的EF并采用的仓储Repository模式

Repository模式还不是很清楚的可以先学习一下我之前的文章:

NopCommerce源码架构详解-MVC5使用EF6实现Repository模式相关源码分析

一、IRepository<T>

首先,Nop定义了一个通用的泛型接口:

Nop.Core.Data.IRepository<T>

里面定义了常用的增、删、查、改等操作方法,但是由于是接口,只是方法定义没有实现。

声明成泛型的好处只用定义一些通用的方法,这样可以适用于所有的表。而不用每一个表单独定义一个类重复这些增、删、查、改方法。

二、EfRepository<T>

Nop.Data.EfRepository<T>就是上面接口Nop.Core.Data.IRepository<T>的EF具体实现。

可以看到使用了EF相关的API,比如:DbContext,DbSet等,下面我具体来看一下插入、添加一条记录的方法:

三、依赖注入

Nop里面代码到处都充分体现了面向接口编程,所有代码你F12跟踪进去都是只定位到对应的接口。

查看Controller代码看到Controller引用是都是Service的接口,如图:

Nop里是通过Autofac对mvc的Controller进行依赖注入的。MVC的依赖注入可以参考:

什么是ASP.NET MVC的依赖注入控制反转

IoC实践--用Autofac实现MVC5.0的IoC控制反转方法


这个时候我们要看这些Service接口的具体实现才能找到其“庐山真面目”。

我们随便找一个Service具体实现

UrlRecordService的一些方法:

public virtual UrlRecord GetBySlug(string slug)
{
	if (String.IsNullOrEmpty(slug))
		return null;

	var query = from ur in _urlRecordRepository.Table
				where ur.Slug == slug
				//first, try to find an active record
				orderby ur.IsActive descending, ur.Id
				select ur;
	var urlRecord = query.FirstOrDefault();
	return urlRecord;
}
public virtual UrlRecordForCaching GetBySlugCached(string slug)
{
	if (String.IsNullOrEmpty(slug))
		return null;

	if (_localizationSettings.LoadAllUrlRecordsOnStartup)
	{
		//获取已缓存全部Url记录数据 
		var source = GetAllUrlRecordsCached();
		var query = from ur in source
					where ur.Slug.Equals(slug, StringComparison.InvariantCultureIgnoreCase)
					//first, try to find an active record
					orderby ur.IsActive descending, ur.Id
					select ur;
		var urlRecordForCaching = query.FirstOrDefault();
		return urlRecordForCaching;
	}

	//gradual loading
	string key = string.Format(URLRECORD_BY_SLUG_KEY, slug);
	return _cacheManager.Get(key, () =>
	{
		var urlRecord = GetBySlug(slug);
		if (urlRecord == null)
			return null;

		var urlRecordForCaching = Map(urlRecord);
		return urlRecordForCaching;
	});
}
/// <summary>
/// Gets all cached URL records
/// </summary>
/// <returns>cached URL records</returns>
protected virtual IList<UrlRecordForCaching> GetAllUrlRecordsCached()
{
	//cache
	string key = string.Format(URLRECORD_ALL_KEY);
	return _cacheManager.Get(key, () =>
	{
		var query = from ur in _urlRecordRepository.Table
					select ur;
		var urlRecords = query.ToList();
		var list = new List<UrlRecordForCaching>();
		foreach (var ur in urlRecords)
		{
			var urlRecordForCaching = Map(ur);
			list.Add(urlRecordForCaching);
		}
		return list;
	});
}

可以从上面代码看到上面通过Repository.Table和linq来获取数据的。上面有用到Nop的缓存管理cacheManager,对这个部分还不太懂的同学可以参考我之前写的文章:NopCommerce源码架构详解-Cache缓存相关源码分析


我们再回过头来看看.Table是什么?

在接口Nop.Core.Data.IRepository<T>里面

然后我们再来看接口的实现Nop.Data.EfRepository<T>对应的实现:

可以看到采用的EF的的DbSet返回表的数据,对使用过EF的同学都不用我再解释了吧?

上面我们有说Controller引用的IXXXService接口,而IXXXService接口的具体实现XXXXXXService又是引用的IXXXRepository接口,IXXXRepository<T>接口具体实现是XXXRepository<T>

不同表,T就相应不同,比如UrlRecordService里面Repository。


最后,Nop里面又怎么设置Nop.Core.Data.IRepository<T>使用是Nop.Data.EfRepository<T>呢?

在项目Nop.Web.Framework里面有一个类DependencyRegistrar专门告诉Autofac依赖注册的。

DependencyRegistrar类里面我们可以找到以下代码:


通过builder.RegisterGeneric可以注册泛型依赖。同理你要可以在这个类里面找到IXXXService的依赖注入。

到此,Nop的使用EF访问数据库就来龙去脉已经清楚,现在你可以打开代码自己DIY。

参考:

NopCommerce源码架构详解--Autofac依赖注入分析
IoC实践--用Autofac实现MVC5.0的IoC控制反转方法


小编蓝狐