Hijri/Gregorian Converter Business Object using CSLA .NET.

Hijri/Gregorian Converter Business Object using CSLA .NET.

Old forum URL: forums.lhotka.net/forums/t/4815.aspx


tarekahf posted on Wednesday, May 07, 2008

I am developing a Business Object using CSLA .NET to perform Conversion from/to Hijri/Gregorian Calendar. Although there is a class in .NET for this purpose, but, still there is a good chance there will be a mistake by at least one day +/- in few cases. In any case, I may depend on this class for conversion, when needed. On the other hand, I already developed this conversion logic under MS Access, and I want to re-use parts of the work done of it in .NET. 

I will post the BO specs summary here to give you an idea about the requirement, so that I can get your feedback, and I will be posting questions mainly related to how to make this BO most efficient, because eventually it will be exposed via a web service.

The Database:

I am storing the required data in tables in MS Access DB, and following is a sample of such tables:

tDOW
DOW DOWArb DOWEng
1 سبت Sat
2 أحد Sun
3 إثنين Mon
4 ثلاثاء Tue
5 أربعاء Wed
6 خميس Thu
7 جمعة Fri

tHMonth
HMnth HMnthNameArb HMnthNameEng DftDays
1 محرم Muharram 29
2 صفر Safar 30
3 ربيع الأول Rabii' I 29
4 ربيع الآخر Rabii' II 29
5 جمادى الأولى Jumada' I 30
6 جمادى الآخرة Jumada' II 29
7 رجب Rajab 29
8 شعبان Sha'ban 30
9 رمضان Ramadan 30
10 شوال Shawal 29
11 ذو القعدة Dhul-Qa'dah 30
12 ذو الحجة Dhu Al-Hijja 30

Following is the main conversion table which is updated/initialized at the beginning of each new Hijri Year and when needed (mainly at the beginning of Ramadan):

tHYearMonth

HYear HMnth DaysCnt FromDateGrg ToDateGrg
1429 1 29 10/01/2008 07/02/2008
1429 2 30 08/02/2008 08/03/2008
1429 3 29 09/03/2008 06/04/2008
1429 4 29 07/04/2008 05/05/2008
1429 5 30 06/05/2008 04/06/2008
1429 6 29 05/06/2008 03/07/2008
1429 7 29 04/07/2008 01/08/2008
1429 8 30 02/08/2008 31/08/2008
1429 9 30 01/09/2008 30/09/2008
1429 10 29 01/10/2008 29/10/2008
1429 11 30 30/10/2008 28/11/2008
1429 12 30 29/11/2008 28/12/2008

BO Class Specs:

Class Name: HijriGreg
Class Member:

  1. LastTimeDataLoaded: The date/time the data was loaded from
  2. DayOfWeek: DataSet/DataView loaded from the related table above.
  3. HijriMonth: DataSet/DataView loaded from the related table above.
  4. HijriYearMonth: DataSet/DataView loaded from the related conversion table above.

Do you have any comment on how to represent the above data in .NET ? I was thinking to use XML, bu I need a quick and easy way to perform look-up which is probably better done using DataView? I need help in this area.

Comments about Class Members:

I want to load the above DataSet/Views once and make them available to all users (Application Scope) to make it more efficient by minimizing Database Access Operations.

Only for the DataSet of HijriYearMonth Conversion Table must be re-loaded say once every few days or something like that, because it may change at the beginning of every month at worst case.

I can make the above members as Public Shared, but this will violate the concept of Encapsulation, so how I can define them in such a way to make them persistent and available to all the users of the application ? Of course, in this case I have to Synchronize the Locks to the shared resources to make it thread safe. I need help in this area.

Initialization Methods:

I think the initialization methods should be called when needed and must be private. For example:

- Sub HijriGreg.InitializeIfNeeded(): It will check if the class variables are Nothing, and load each each one at a time. For the case of the HijriYearMonth Conversion Table, it will check if the data is expired (using LastTimeDataLoaded) and re-loaded if needed.

- Method/Function HijriGreg.GetHijriFromGreg(...) as String:
  - Input: GregDateDMY, a String Variable of input Gregorian Date in DD/MM/YYYY format.
  - Output: Returns a String of HijtiDateDMY in DD/MM/YYY format.
  I am not sure if this method will be Shared or not ? I need help in this area..

- Method/Function HijriGreg.GetGregFromHijri(...) as String:
  - Input: HijriDateDMY, a String Variable of Hijri Date in DD/MM/YYYY format.
  - Output: Returns a String of HijtiDateDMY in DD/MM/YYY format.
  I am not sure if this method will be Shared or not ? I need help in this area..

The algorithms for the above methods are available with me and already implemented in VBA and it is working properly for the past 5 years.

How to make the BO HijriGreg visible to all users:

Should I create an instance of the HijriGreg Object and store it in Application(..) variable ? So that in the subsequent calls to this object, it can be restored from the Application Variable Objects.

How to make such process thread safe ?

I need help in this area.

After implementing this BO, I need to wrap it in a Web Service. I will talk about this later.

Thank you for your help in advance.

Tarek.

KennyKen replied on Wednesday, May 07, 2008

tarekahf:
Do you have any comment on how to represent the above data in .NET ? I was thinking to use XML, bu I need a quick and easy way to perform look-up which is probably better done using DataView? I need help in this area.

There are many options to choose from.  CSLA business objects would do this nicely.  Alternatively, you could use a DataSet to hold the data.  A DataView is used to look at data in a DataSet.

tarekahf:
I can make the above members as Public Shared, but this will violate the concept of Encapsulation, so how I can define them in such a way to make them persistent and available to all the users of the application ? Of course, in this case I have to Synchronize the Locks to the shared resources to make it thread safe. I need help in this area.

This sounds like the Singleton pattern.  I don't know that you would need to synchronize anything since you will always be reading the data and never writing to it.  Writes would obviously need to be synchronized.

tarekahf:
- Method/Function HijriGreg.GetHijriFromGreg(...) as String:
  - Input: GregDateDMY, a String Variable of input Gregorian Date in DD/MM/YYYY format.
  - Output: Returns a String of HijtiDateDMY in DD/MM/YYY format.
  I am not sure if this method will be Shared or not ? I need help in this area..

- Method/Function HijriGreg.GetGregFromHijri(...) as String:
  - Input: HijriDateDMY, a String Variable of Hijri Date in DD/MM/YYYY format.
  - Output: Returns a String of HijtiDateDMY in DD/MM/YYY format.
  I am not sure if this method will be Shared or not ? I need help in this area..

I would make both of these methods shared/static since they wouldn't use any class's member fields.

tarekahf:
Should I create an instance of the HijriGreg Object and store it in Application(..) variable ? So that in the subsequent calls to this object, it can be restored from the Application Variable Objects.

How to make such process thread safe ?

I need help in this area.

If those are the only methods (GetGregFromHijri and GetHijriFromGreg) that you're trying to support then I would recommend making them Shared/Static methods on a utility class which then use Singleton instances of the lookup tables you described.  You wouldn't store anything in Application variables.  The process is already thread safe because data is only being read, not updated/written.

-- Ken

tarekahf replied on Wednesday, May 07, 2008

Ken, thanks a lot for your great feedback.

Please allow me to clarify some points as follows and and rephrase some questions:

- I think using DataView/DataSet to hold the data in the tables is probably better than using CSLA List Objects, this is because I think such CSLA Objects are used for the purpose of Data Binding and exposing the content of RDBMS Tables to the Presentation Layer. However, in my case, these tables are used by the algorithm which is converting from/to Hijri/Gregorian, and the result is a simple String. Probably, I can use CSLA to make the result of the conversion bind-able to UI Controls.

- I was thinking to use Singleton Object, but was not sure if such object will survive (remain active) across multiple calls from the Client to the Web Server (after a round trip). I always thought that I have to create such object and store it in an Application Variable to make it visible to current and all other threads/users of the application and to avoid creating it more than once and to avoid loading the DataSets over and over.

I want to load the tables into member variables as DataSets only once, and I want them to be accessible (public) for all the users of this HijriGreg Singleton Object.  How I can achieve this in .NET/CSLA ?

- Yes, in general I am not writing to the tables, and they are mainly used for reading. Only one table will be initialized once every year, and rarely will e updated during the year, and such updates will be carried out only by authorized users. I think I need to Synchronize the process only at the time of loading the DataSets, since this is the only time when the program is writing to memory variables (DataSet). I think I still need to synchronize writes to public shared memory variables. Correct ?

- For the time being, I only have the methods "GetHijriFromGreg" and "GetGregFromHijri" they will have to use the member variables which are actually the DataSets/DataViews which represent the tables mentioned earlier. They will be used to perform the conversion and optionally return the DOW Name and Hijri Month Name, if needed.

So, probably I will make such methods as Public Shared/Static and the related member variables (DataSet/DataViews) must be in this case as "private shared/static". No one outside the scope of the HijriGreg object need to know anything about the internal details of the tables/data used to perform the conversion. Correct ?

Also, as per my understanding is that a Static/Shared methods can be called without the need to create an instance of the class. Also, shared methods can use shared variables which are visible to all the users of the class/object. As a mater of fact, this concept is still not 100% clear to me and still seems confusing to me, and not yet sure how to use it to meet my requirements. The reason why I am confused is that when I use a Singleton object, this means I will have to instantiate a Single Object of the HijriGreg Class, and in this case, there is no need to make such methods as Public/Share. I still need help here.

Your feedback will be appreciated.

Tarek.

KennyKen replied on Thursday, May 08, 2008

tarekahf:
- I was thinking to use Singleton Object, but was not sure if such object will survive (remain active) across multiple calls from the Client to the Web Server (after a round trip). I always thought that I have to create such object and store it in an Application Variable to make it visible to current and all other threads/users of the application and to avoid creating it more than once and to avoid loading the DataSets over and over.I want to load the tables into member variables as DataSets only once, and I want them to be accessible (public) for all the users of this HijriGreg Singleton Object.  How I can achieve this in .NET/CSLA ?

A singleton instance would behave the same as an Application variable.  It is created/instantiated the first time the web application/service references it.  It falls out of scope/is destroyed when the application is unloaded.

public class MySingleton
{
   private static MySingleton _instance = new MySingleton();
   public static MySingleton Instance { get { return _instance; } }
   private MySingleton() { /* your initialization code goes here */ }
}

tarekahf:
- Yes, in general I am not writing to the tables, and they are mainly used for reading. Only one table will be initialized once every year, and rarely will e updated during the year, and such updates will be carried out only by authorized users. I think I need to Synchronize the process only at the time of loading the DataSets, since this is the only time when the program is writing to memory variables (DataSet). I think I still need to synchronize writes to public shared memory variables. Correct ?

I understand what you're saying but it's my understanding (and maybe I am wrong) that if you implement the singleton pattern how I have it above then you do not need to syncrhonize anything.  If you can guarnatee the web application gets restarted after you update the lookup tables then everything should work as intended.

tarekahf:
- For the time being, I only have the methods "GetHijriFromGreg" and "GetGregFromHijri" they will have to use the member variables which are actually the DataSets/DataViews which represent the tables mentioned earlier. They will be used to perform the conversion and optionally return the DOW Name and Hijri Month Name, if needed.

So, probably I will make such methods as Public Shared/Static and the related member variables (DataSet/DataViews) must be in this case as "private shared/static". No one outside the scope of the HijriGreg object need to know anything about the internal details of the tables/data used to perform the conversion. Correct ?

Also, as per my understanding is that a Static/Shared methods can be called without the need to create an instance of the class. Also, shared methods can use shared variables which are visible to all the users of the class/object. As a mater of fact, this concept is still not 100% clear to me and still seems confusing to me, and not yet sure how to use it to meet my requirements. The reason why I am confused is that when I use a Singleton object, this means I will have to instantiate a Single Object of the HijriGreg Class, and in this case, there is no need to make such methods as Public/Share. I still need help here.

Okay, there are many, many ways of architecting this.  Here's how I would do it.  I'm sure other people will have different ways.

A class HijriLookupDataSet which inherits DataSet and implements the Singleton pattern I described above.  In the class's private constructor I would create the DataTables and load the data into them.

Another class called HijriDateUtilities that had the two static methods.  This class would implement the two methods by using HijriLookupDataSet.Instance.

When you need to use those functions you would do something like:  TextBox1.Text = HijriDateUtilities.GregToHijri(System.DateTime.Now.ToString("M/d/yyyy"));

-- Ken

tarekahf replied on Friday, May 09, 2008

Ok, great ! I liked the Singleton implementation.

Just to reassure about the following points:

1. What is the added value of putting HijriLookupDataSet in  different class than that of the class HijriDateUtilities ? Is it for the purpose of separating Data Layer from the Business Layer or for the purpose making the Singleton Object to as a reusable shared object which has the required data ?

2. I prefer to hide the internal implementation of the data used to perform the conversion. If I expose the Dataset Singleton Object to other developers, they they will be tempted to develop other conversion implementations.

How about consolidating both classes into one class (for simplifying the implementation) and make it as a Singleton object, and hide the internal implementation of the Lookup Tables (Encapsulation) ? Or, is there a way to prevent others from using the Singleton object directly by using special declaration qualifiers or something like that ?

3. In case I will be using an Instantiated (Singleton) Object, then I do not see the need to make the methods "HijriToGreg" and "GregToHijri" as static/shared. So I think making them as public methods will do also. What do you think ? In other words, it does not mater in this case how such methods will be declared, right ?

4. The conversion methods mentioned earlier will have to use some intermediate variables to perform the conversion, and of course, such (temporary memory) variables will be updated in different ways. Since we have only one instance of this object, then it appears to me that we have to Synchronize both conversion methods, because we have only one object and all callers are using the same methods and same variables, even if such variable are local to the method. Correct ?

5. If I use one Singleton object/class, then I think I have to initialize it using some kind of Factory Method in the Global.asax Event "Application_OnStart" or something like that ? The same applies if I use one Singleton Object for Dataset and one class for the conversion logic ?

Tarek.

tarekahf replied on Saturday, May 10, 2008

I have developed a sample Class Library to test to Singleton concept and it worked 100% as expected ... Thanks a lot Ken for guiding me to this direction.

As a mater of fact, most questions above have been answered after I developed the sample project.

In general, I will use one class to encapsulate the object's data and its behavior (logic). This same class will implement the Singleton object also.

Since there is only one object, then any variables updated inside this object must be synchronized, so all methods (public shared or public only) will have to be synchronized. The only exception to this is the Static Initialization of the Singleton during declaration, as in this case .NET framework will ensure that the update is synchronized.

This means that the methods "HijriToGreg()" and "GregToHijri()" must be synchronized. Please correct me if I am wrong.

I noticed that the Singleton object is created at the first time a reference is made to the class members. But, I could not find and easy way to destroy the object, and force re-initialization, and this only could happen after I restart IIS. I also implemented IDisposable Class but still not working. But if I use "lazy initialization" i.e. manual creation of the Singleton, then I can control the Disposal and re-creation of the object.

Tarek.

ajj3085 replied on Monday, May 12, 2008

Yes, you'll have to ensure that all instance members are syncronized properly.  If you want to re-initialize the singleton, you'll have to do so by providing a method.  Likely just setting the static instance to null, and again you'll have to ensure that method is syncronized.

tarekahf replied on Monday, May 12, 2008

ajj3085:
Yes, you'll have to ensure that all instance members are syncronized properly.

Ok, great ! I was thinking about the difference of shared and non-shared methods. Also, such methods have local variables. I was thinking that only and only if I use non-shared (non-static) methods, which are updating local variables to the method, then in this case there is no need to synchronize such methods. All other shared methods/variables need need to by synchronized. Correct ?

I am asking this because I could not find a reference document talking about this subject which is very important. All references are talking about the need to sync the initialization of the Singleton.

If you want to re-initialize the singleton, you'll have to do so by providing a method.  Likely just setting the static instance to null, and again you'll have to ensure that method is syncronized.

I created a shared method method "reset()" which simply makes the shared instance as Nothing. And I create a Factory Shared Method "GetSingleton()" to create the shared instance. I have tested this and it is working. But, since I am just making the instance as nothing, then is there a need to sync this method ?

Tarek.

tarekahf replied on Saturday, May 17, 2008

Completed the design and implementation of HijriGregCalendar.

Mainly, it has the following 2 public methods:

1. Public Function HijriToGreg(HijriDateDMY as String) as string,

2. Public Function GregToHijri(GregDateDMY as String) as String.

and one Public Shared Method:

public shared GetSginleton() as HijriGregCalendar

And I used CSLA .NET Data Access approach to load the lookup tables into the DataViews members of this class.

Everything is working properly when I test the above class from a normal ASPX Web Page.

But, when I tried to develop a Web Service wrapper for the above class, I am unable to call the GetSingleton() method to get shared instance object of this class. This method is not visible from Web Service. Other methods are visible.

Any idea why ? What is the proper way to provide the above functionality under a Web Service ?

Tarek.

tarekahf replied on Monday, May 19, 2008

Everything is OK now. In case someone is interested, I am able to call the HijriGregCalendar via a Web Service Wrapper Class from VB Script as follows:


Const BaseWebServiceURL = "http://server/cslawebservices/HijriGreg/"
Const WebService = "HijriGregService.asmx"
Const Operation = "HijriToGreg"
Const prmHijriDateDMY= "1/5/1429"
Const prmGregDateDMY = "1/5/2008"
dim PostedURL
dim xmlhttp
' Create the HTTP object
Set xmlhttp = CreateObject("Microsoft.XMLHTTP")
PostedURL = BaseWebServiceURL & WebService
'msgbox "Posted URL = " & PostedURL
'xmlhttp.open "POST", PostedURL, false
'xmlhttp.setRequestHeader "Content-Type", "text/xml"

'MsgBox xmlhttp.responseText

MsgBox "Hijri conversion from " & prmHijriDateDMY & " to Greg is: " & HijriToGreg(prmHijriDateDMY)

MsgBox "Gregorian conversion from " & prmGregDateDMY & " to Hijri is: " & GregToHijri(prmGregDateDMY)

function HijriToGreg(prmHijriDateDMY)
xmlhttp.open "POST", PostedURL, false
xmlhttp.setRequestHeader "Content-Type", "text/xml"
xmlhttp.setRequestHeader "SOAPAction", "WebServices.HijriGreg/HijriToGreg"
PostMsg = _
"<?xml version=""1.0"" encoding=""utf-8""?> " & _
"<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/""> " & _
"<soap:Body> " & _
" <GregToHijri xmlns=""WebServices.HijriGreg""> " & _
" <GregDateDMY>" & prmGregDateDMY & "</GregDateDMY> " & _
" </GregToHijri> " & _
"</soap:Body> " & _
"</soap:Envelope>"

xmlhttp.send PostMsg

'MsgBox xmlhttp.responseText
HijriToGreg = xmlhttp.responseXML.selectSingleNode("//HijriToGregResult").text
end function

function GregToHijri(prmGregDateDMY)
'Set xmlhttp = CreateObject("Microsoft.XMLHTTP")
'PostedURL = BaseWebServiceURL & WebService
'msgbox "Posted URL = " & PostedURL

xmlhttp.open "POST", PostedURL, false
xmlhttp.setRequestHeader "Content-Type", "text/xml"
xmlhttp.setRequestHeader "SOAPAction", "WebServices.HijriGreg/GregToHijri"
PostMsg = _
"<?xml version=""1.0"" encoding=""utf-8""?> " & _
"<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/""> " & _
"<soap:Body> " & _
" <GregToHijri xmlns=""WebServices.HijriGreg""> " & _
" <GregDateDMY>" & prmGregDateDMY & "</GregDateDMY> " & _
" </GregToHijri> " & _
"</soap:Body> " & _
"</soap:Envelope>"
xmlhttp.send PostMsg

'MsgBox xmlhttp.responseText
GregToHijri = xmlhttp.responseXML.selectSingleNode("//GregToHijriResult").text
end function

Tarek.

Copyright (c) Marimer LLC