Monday, April 24, 2006

CSLA .Net - My favorite base framework for .NET

I was introduced to CSLA Framework about 2 years back by 2 smart client side resources on one of the projects I was handling. As soon as I read the intro and delved into sample programs, I liked the CSLA framework for its simplicity, extensibility and the features it offered. At that time the samples that it included had various flaws. For example, if a class was switchable then there was a lot of code repetation in DataPortal_Fetch and Fetch() methods. In such cases, the easy way out was calling Fetch() method from DataPortal_Fetch etc. That was an easy fix.

Apart from that, I read into many hate stories in terms of maintenance being tough etc but with applying some nicer aspects of Inheritence and using code generators like Code-Smith I found it to be an easy-to-use base framework which you can develop on. Right now, almost all my application are based on CSLA as the base and then some additional framework on top of it. I'll be sharing some of the insights on the changes or my experiences in my future posts. However, at this point, I would like to share some of the important links from CSLA learning/ understanding perspective:

CSLA.NET Goals: http://www.lhotka.net/Articles.aspx?id=077469bf-a425-48a5-8b63-3f2382a079ff
Why is the data access in the business class? http://www.lhotka.net/Articles.aspx?id=b99dfec2-c079-4b85-98df-ea3582c28386
Concurrency http://www.lhotka.net/Articles.aspx?id=890d3e3c-8a49-486c-ae48-a44e7e1f7844

Should factory methods catch data exceptions? http://www.lhotka.net/Articles.aspx?id=df4ed914-e910-4ece-9328-d8446e091497

Rolling back object state when DataPortal_Update fails http://www.lhotka.net/Articles.aspx?id=e3a848aa-2150-47d1-b79e-a605016e05b0

Inheritance and data access in CSLA .NET http://www.lhotka.net/Articles.aspx?id=e130b265-15cb-453d-9719-d5a944385fd3

As suggested in "Inheritence and data access in CSLA.Net", I've base framework as something like

Durlabh.BusinessObject : Csla.BusinessObject

and so on. This way, all my application refer to the custom framework instead of directly relying on Csla. This makes it easier to upgrade. In addition, I've centered all my data access around Microsoft Practices Enterprise Library and the custom framework has in-built:
  • Database Interaction: Main classes only interact with IDataReader to read the data. This way, my business objects are not tied with the database provider. Additionally, connection opening and closing is part of the core classes.
  • Concurrency Handling: Almost all of my applications require concurrency handling. This has also been centralized in the core classes.
  • Security: Business Object level security is something that most of the application frameworks/ designs tend to ignore. Our custom framework implementation has provision for this.

In addition, all my Editable Business Objects share some of the optional common properties that are stored in the core object instead of specifying in each object:

  • Id: Primary Key
  • ModifiedOn - Modification log related info
  • ModifiedBy - Modification log related info
  • Version - for concurrency handling
  • UserId - current logged in user Id as per the security context

This way, we have our business object's fetch method something like this:

using(SafeDataReader dr = base.GetReaderByStoredProc(DataOperationMode.Get))

{

// read common attributes such as Id, version etc.

base.ReadCommonAttributes(dr)

customerName = dr.GetAnsiString("CustomerName");

}

This way, my business objects do not need to deal with connections etc. Stored procedure name is also determined in the base classes based on operation mode. Similarly, during update we'll have calls something like:

using(DbCommand cm = base.GetCommand(DataOperationMode.Update))
{

db.AddInParameter(cm, "CustomerName", dbType.AnsiString, customerName);

base.ExecuteNonQuery(cm);
}

Db is the database object available through base class. ExecuteNonQuery in the base class takes care of various things such as:

  1. Adding common parameters such as for Id, Version, NewVersion, UserId etc.
  2. Checking for concurrency related update failures
  3. Raising exception/ basic exception handling

This makes our data access code much cleaner in the Business Objects. In addition, since code is centralized in couple of classes, we can easily modify the code. We also try to minimize the changes required to auto-generated classes through one of my favorite tools - CodeSmith. With minimal modifications, we can easily re-generate the classes if any modifications are required.

More on my base classes and code smith later. I just grabbed a copy of Expert C# 2005 Business Objects book and I must go through it to ensure I understand new concepts.

No comments: