最近粗略的研究了
dnn
的数据访问机制,记录一下学习结果。
dnn
的页面、模块可按照组进行授权,本来想先研究
dnn
是如何设计权限控制模块的,把权限相关的表结构及关系搞清楚后开始看代码,这一看就钻到数据访问的问题上来了,这一层不弄清楚在其他问题也不容易搞明白,那就从底层的数据访问层开始看吧。
前辈们的早研究过这些问题了,首先就是搜相关的资料,这篇是不能不看的:
DNN 数据访问策略【译】:http://michaelj.cnblogs.com/archive/2005/08/11/212532.html
dnn
的数据库访问类运用了Reflection factory
和Singleton
模式,
Reflection factory
模式通过反射在应用程序运行时动态的加载正确的(适合的)数据访问对象。
Reflection factory 是这样实现的:先创建一个抽象类,这个类声明了一个方法,这个方法是每一个数据访问类都必须继承实现的。对每一个支持的数据库,创建了一个具体的实现类,这个类实现了抽象类或“协议”中定义的各种数据库操作的代码。为了支持在运行时动态加载具体的操作类,在工厂里实现了一个
Instance()
方法,这个方法依赖于提供者类从配置文件读取并反射过来的值来决定需要加载哪个程序集。
这几篇文章都不错,推荐一下。
Singleton
模式的介绍 http://www.cnblogs.com/zhenyulu/articles/37246.html
factory
模式的介绍 http://www.cnblogs.com/zhenyulu/articles/36590.html
反射工厂介绍 http://www.cnblogs.com/fineboy/archive/2005/08/03/206244.html
在
Dataprovider.vb
中定义了
DataProvider
抽象类:
包含了
DNN
的核心框架的数据访问方法。它包含了一个工厂本身的实例方法(
Instance
()),它负责在运行时动态加载
web.config
中描述的合适的程序集。例如SqlDataProvider继承了DataProvider,DataProvider中定义了抽象方法在sql server 下的实现。
Dataprovider.vb中对应的关键代码:
Singleton 模式要解决的两个基本问题是全局访问和实例化控制,我对为什么要在这里用Singleton 模式还不理解,有什么好处呢?只产生一个dataprovider实例,对数据库的操作都通过这个实例的方法进行。我能想到的好处是只有一个实例,且该实例为静态的,省内存,效率高。如果有多个实例会出现什么问题呢?希望兄弟们能够指点迷津。
Shared/Static Methods
#Region "Shared/Static Methods"

' singleton reference to the instantiated object
Private Shared objProvider As DataProvider = Nothing
'Shared 关键字指示一个或多个被声明的编程元素将被共享。共享元素不关联于某类或结构的特定实例。
'可以通过使用类名或结构名称或者类或结构的特定实例的变量名称限定共享元素来访问它们。
'VB.net中的shared关键字对应着C#的Static关键字
'Singleton 模式解决的两个基本问题:全局访问和实例化控制。

' constructor 静态构造器,在静态字段初始化之前初始化

Shared Sub New()Sub New()
CreateProvider()
End Sub

' dynamically create provider

Private Shared Sub CreateProvider()Sub CreateProvider()
objProvider = CType(Framework.Reflection.CreateObject("data"), DataProvider) '运用反射机制动态创建实际的DataProvider
End Sub

' return the provider

Public Shared Shadows Function Instance()Function Instance() As DataProvider
Return objProvider
End Function

#End Region
其中 objProvider = CType(Framework.Reflection.CreateObject("data"), DataProvider) 调用了DotNetNuke.Framework.Reflection中的方法创建web.config中设定的DataProvider,
Reflection.vb中的相关实现:
关于Activator.CreateInstance:
Public
Shared
Function CreateObject()
Function CreateObject(ByVal TypeName As String, ByVal CacheKey As String, ByVal UseCache As Boolean) As Object

' dynamically create the object
Return Activator.CreateInstance(CreateType(TypeName, CacheKey, UseCache))

End Function
Reflection.vb 中的CreateType方法实现dataprovider的缓存的管理,反射是比较耗资源的,缓存起来直接返回dataprovider就行了,我发现每次开机后第一次打开dnn首页的时候很慢,大概要十几秒,之后再打开时就很快,应该就跟此类的缓存有关系。
Public
Shared
Function CreateType()
Function CreateType(ByVal TypeName As String, ByVal CacheKey As String, ByVal UseCache As Boolean, ByVal IgnoreErrors As Boolean) As Type

If CacheKey = "" Then
CacheKey = TypeName
End If

Dim objType As Type = Nothing

' use the cache for performance
If UseCache Then
objType = CType(DataCache.GetCache(CacheKey), Type)
End If

' is the type in the cache?
If objType Is Nothing Then
Try
' use reflection to get the type of the class
objType = BuildManager.GetType(TypeName, True, True)

If UseCache Then
' insert the type into the cache
DataCache.SetCache(CacheKey, objType)
End If
Catch exc As Exception
' could not load the type
If Not IgnoreErrors Then
LogException(exc)
End If
End Try
End If

Return objType
End Function
说起来也毕业两三年了,感觉是混了三年,写的代码基本上是拖控件写sql的层次,看了dnn的真的有久旱逢甘露的感觉,老婆说我每天上班对着电脑,回来还盯着看代码,真不明白那有什么好看的也不嫌烦,我只能说我的快乐她不懂!呵呵,又被着睡觉了,哎,怪不得和尚要不结婚呢,有了家就不能安心修行了,哈哈