Hydrating your Business Objects - Part 2, The IHydratable Interface

http://www.charlesnurse.com/post/Hydrating-your-Business-Objects-Part-2-The-IHydratable-Interface.aspx

This article is based on material originally published on DNN Developer Zone (www.dnndevzone.com).  This version has been updated to cover the changes made in DotNetNuke 5.0.

In a previous blog I discussed how the CBO class is used to hydrate custom business objects.  The CBO class's methods are useful as they provide a simple API for developers building Modules.  Using the Links module as an example, there are two methods in the LinksController class that use the CBO class (see Listing 1)

Listing 1: The GetLink and GetLinks methods of the LinksController
   1:  Public Function GetLink(ByVal ItemID As Integer, ByVal ModuleId As Integer) As LinkInfo
   2:      Return CType(CBO.FillObject(DataProvider.Instance().GetLink(ItemID, ModuleId), 
GetType(LinkInfo)), LinkInfo)
   3:  End Function
   4:   
   5:  Public Function GetLinks(ByVal ModuleId As Integer) As ArrayList
   6:      Return CBO.FillCollection(DataProvider.Instance().GetLinks(ModuleId), 
GetType(LinkInfo))
   7:  End Function

The CBO class is very useful as it abstracts away the details of hydrating your objects.   It also handles the management of the DataReader, making sure that the DataReader is closed when finished with.  This is very important as the DataReader keeps a connection open to the Database.

There is however a cost in this abstraction - performance.  The CBO HydrateObject private method uses Reflection to set the objects property values to the columns in the DataReader, and Reflection is typically slow.  In DotNetNuke version 4.4.0 I introduced some custom hydration methods into the core so that mission-critical classes were hydrated explicitly, avoiding the performance hit from Reflection. 

So if we use one of the CBO classes Fill... methods we have a performance hit from the sue of Reflection, and if we use a custom hydrator we have the responsibility of managing the DataReader pplus the complexity of creating the custom hydrators.

The IHydratable Interface

To solve this problem the IHydratable Interface was introduced in DotNetNuke version 4.6.0.  This interface consists of a property and a method. (see Listing 2)

Listing 2: The IHydratable Interface
   1:  Public Interface IHydratable
   2:      Property KeyID() As Integer
   3:      Sub Fill(ByVal dr As IDataReader)
   4:  End Interface

The KeyID property identifies a unique identifier for the instance of the object.  This is used by the FillDictionary method as the key for filling the collection, and for the most part can be implmented to wrap the existing identifier (ItemID in the case of the LinksInfo class)

Listing 3: The KeyID property implemented in LinksInfo
   1:  Public Property KeyID() As Integer Implements IHydratable.KeyID
   2:      Get
   3:          Return ItemId
   4:      End Get
   5:      Set(ByVal value As Integer)
   6:          ItemId = value
   7:      End Set
   8:  End Property

The Fill method is the important member of the Interface for the purposes of this discussion (see Listing 4).

Listing 4: The Fill method implemented in LinksInfo
   1:  Public Sub Fill(ByVal dr As System.Data.IDataReader) Implements IHydratable.Fill
   2:      ItemId = Convert.ToInt32(Null.SetNull(dr("ItemId"), ItemId))
   3:      ModuleId = Convert.ToInt32(Null.SetNull(dr("ModuleId"), ModuleId))
   4:      Title = Convert.ToString(Null.SetNull(dr("Title"), Title))
   5:      Url = Convert.ToString(Null.SetNull(dr("URL"), Url))
   6:      ViewOrder = Convert.ToInt32(Null.SetNull(dr("ViewOrder"), ViewOrder))
   7:      Description = Convert.ToString(Null.SetNull(dr("Description"), Description))
   8:      CreatedByUser = Convert.ToInt32(Null.SetNull(dr("CreatedByUser"), CreatedByUser))
   9:      CreatedDate = Convert.ToDateTime(Null.SetNull(dr("CreatedDate"), CreatedDate))
  10:      TrackClicks = Convert.ToBoolean(Null.SetNull(dr("TrackClicks"), TrackClicks))
  11:      NewWindow = Convert.ToBoolean(Null.SetNull(dr("NewWindow"), NewWindow))
  12:  End Sub

This method sets the value of each property from the related column of the DataReader - without using Reflection, as we know which column relates to which property.   The CBO class's FillObjectFromReader method checks if the object implements IHydratable, and if it does it casts the object as IHydratable and calls the Fill method.  The Fill method (see Listing 4) processes the DataReader and returns control to the CBO which manages the DataReader and returns the object to the calling method.

The advantage of this approach is that the only difference between the approaches is that one requires the implementation of an Interface.  When you are first developing a new Module you should use the CBO methods, without implementation of IHydratable and then implement the interface when you are sure that the performance gains warrant the extra work.  Either way, you should be confident that the DataReader is managed and you are not leaving any open database connections.


  • 0
    点赞
  • 0
    收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值