/////////////////////////////////////////////////////////// // Bool.cs // Implementation of Class NotifyEventOfInterestFetcher // CSLA type: Read-only object // Created on: 04-Oct-2005 // Object design: John // Coded: John 04-Oct-2005 /////////////////////////////////////////////////////////// using System; using System.Data; using CSLA.Data; using GZTW.Data; using CSLA; using System.Threading; using CSLA.Security; using System.Collections; namespace GZTW.AyaNova.BLL { #pragma warning disable 1591 /// /// Used for determining if an event is of interest for notification purposes /// [Serializable,System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] public class NotifyEventOfInterestFetcher : ReadOnlyBase { // Create a logger for use in this class //private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); #region Attributes private bool mInterested=false; #endregion #region Constructor /// /// Private constructor to prevent direct instantiation /// private NotifyEventOfInterestFetcher() { } #endregion #region Business properties public bool Interested { get { return mInterested; } } #endregion #region System.Object overrides #endregion #region Static methods /// /// Load a fetcher for event /// /// /// /// /// private static NotifyEventOfInterestFetcher GetItem(RootObjectTypes RootObjectType, int EventType, Guid GuidValue)//case 1964 added guidvalue { ////case 1039 //log.Debug("NotifyEventOfInterestFetcher.GetItem(" + RootObjectType.ToString() + " Event ID: " + EventType.ToString() + ")"); return (NotifyEventOfInterestFetcher)DataPortal.Fetch(new Criteria( RootObjectType, EventType, GuidValue)); } /// /// Check to see if there is interest in the event and object specified /// /// /// /// /// public static bool IsEventInteresting(RootObjectTypes RootObjectType, int EventType, Guid GuidValue) { NotifyEventOfInterestFetcher neif= NotifyEventOfInterestFetcher.GetItem(RootObjectType,EventType, GuidValue); return neif.Interested; } /// /// Called internally by the NotifySubscription class when a user deletes or creates a /// notification subscription. /// /// This ensures that the EventOfInterest table is kept up to date with subscriptions /// /// /// /// /// Optional event specific data internal static void Subscribe(RootObjectTypes RootObjectType,int EventType, Guid GuidValue, bool Subscribe) { EventOfInterestManager.Subscribe(RootObjectType, EventType, GuidValue, Subscribe); } #endregion #region DAL DATA ACCESS /// /// protected override void DataPortal_Fetch(object Criteria) { Criteria crit = (Criteria)Criteria; // SafeDataReader dr = null; try { //bugbug: This is not checking with guid value included so //the result is random and could be false negative if there is another with same type and event but different guid DBCommandWrapper dbCommandWrapper = DBUtil.DB.GetSqlStringCommandWrapper( "SELECT aSubscriberCount FROM aNotifyEventOfInterest " + "WHERE (aRootObjectType = @RootObjectType) " + "AND (aEventType = @EventType) " + (crit.GuidValue == Guid.Empty ? "" : "AND (aGuidValue = @GuidValue)")//case 1964 ); dbCommandWrapper.AddInParameter("@RootObjectType",DbType.Int16,(int)crit.RootObjectType); dbCommandWrapper.AddInParameter("@EventType",DbType.Int16,crit.EventType); //case 1964 if (crit.GuidValue != Guid.Empty) dbCommandWrapper.AddInParameter("@GuidValue", DbType.Guid, crit.GuidValue); dr = new SafeDataReader(DBUtil.DB.ExecuteReader(dbCommandWrapper)); if(dr.Read()) { //******************************************* //Are there more than zero subscribers to this event? if(dr.GetInt32("aSubscriberCount")<1) this.mInterested=false;//Nope else//There is at least one subscriber so yes, there is interest this.mInterested=true; //******************************************* } else//couldn't read the record, probably no one has subscribed yet so no, there is no interest in the event this.mInterested=false; } finally { if(dr!=null) dr.Close(); } } #endregion #region criteria /// /// Criteria for identifying existing object /// [Serializable] private class Criteria { public RootObjectTypes RootObjectType; public int EventType; //case 1964 public Guid GuidValue; public Criteria(RootObjectTypes _RootObject, int _EventType, Guid _GuidValue) { RootObjectType=_RootObject; EventType=_EventType; //case 1964 GuidValue = _GuidValue; } } #endregion #region Add events of interest / update subscriber count /// /// Add events of interest / update subscriber count /// [Serializable, System.ComponentModel.Browsable(false)] public class EventOfInterestManager//DO_NOT_OBFUSCATE { bool _Subscribe=false; RootObjectTypes _RootObjectType; int _EventType; Guid _GuidValue; public EventOfInterestManager(RootObjectTypes RootObjectType,int EventType, Guid GuidValue, bool Subscribe) { _Subscribe=Subscribe; _RootObjectType=RootObjectType; _EventType=EventType; _GuidValue=GuidValue; } public static void Subscribe(RootObjectTypes RootObjectType,int EventType, Guid GuidValue, bool Subscribe) { DataPortal.Update(new EventOfInterestManager(RootObjectType, EventType, GuidValue, Subscribe)); } public void DataPortal_Update() { //This method must be rock solid or there could be inconsistent values //in notifyevent causing event's to be Processed un-neccessarily or //worse event's to not be Processed because it appears there is non interest //in them due to an invalid "balance" in the subscriber count. //Start a transaction here and locklevel=System.Data.IsolationLevel.Serializable using (IDbConnection connection = DBUtil.DB.GetConnection()) { connection.Open(); IDbTransaction transaction = connection.BeginTransaction(System.Data.IsolationLevel.Serializable); SmartDate mCreated = new SmartDate(DBUtil.CurrentWorkingDateTime); int nCurrentCount=0; bool nRecordExists=false; SafeDataReader dr = null; DBCommandWrapper cm = null; try { DBCommandWrapper dbCommandWrapper = DBUtil.DB.GetSqlStringCommandWrapper( "SELECT aSubscriberCount, aCreated FROM aNotifyEventOfInterest " + "WHERE (aRootObjectType = @RootObjectType) " + "AND (aEventType = @EventType) " + (_GuidValue==Guid.Empty?"":"AND (aGuidValue = @GuidValue)") ); dbCommandWrapper.AddInParameter("@RootObjectType",DbType.Int16,(int)_RootObjectType); dbCommandWrapper.AddInParameter("@EventType",DbType.Int16,_EventType); if(_GuidValue!=Guid.Empty) dbCommandWrapper.AddInParameter("@GuidValue",DbType.Guid,_GuidValue); dr = new SafeDataReader(DBUtil.DB.ExecuteReader(dbCommandWrapper,transaction)); if(dr.Read()) { //******************************************* nCurrentCount=dr.GetInt32("aSubscriberCount"); mCreated=DBUtil.ToLocal(dr.GetSmartDate("aCreated")); nRecordExists=true; //******************************************* } dr.Close(); //If they are unsubscribing and there is no current record for this event of interest //then just bail. This shouldnt' happen unless there is something funky going on //but covers all eventualities just in case if(!_Subscribe && !nRecordExists) { throw(new ApplicationException( "INTERNAL ERROR: EventOfInterestManager - error attempting an unsubscribe.\r\n" + "No matching record in NotifyEventOfInterest table.\r\n" + "Please report this error immediately to AyaNova support for analysis.")); } //If there is an existing record then update it if(nRecordExists) { //set the current count to what it *should* be if(_Subscribe) nCurrentCount++; else nCurrentCount--; //Just to cover our bases, there shouldn't really be less than zero subscribers if(nCurrentCount < 0) nCurrentCount=0; //Update database cm=DBUtil.GetCommandFromSQL( "UPDATE aNotifyEventOfInterest SET aSubscriberCount=@SubscriberCount, aModified=@Modified, " + "aModifier=@CurrentUserID " + "WHERE (aRootObjectType = @RootObjectType) " + "AND (aEventType = @EventType)"+ (_GuidValue==Guid.Empty?"":"AND (aGuidValue = @GuidValue)")); if(_GuidValue!=Guid.Empty) cm.AddInParameter("@GuidValue",DbType.Guid,_GuidValue); } else { nCurrentCount=1; //add a new event of interest and set it to count 1 cm=DBUtil.GetCommandFromSQL( "INSERT INTO aNotifyEventOfInterest (aRootObjectType, aEventType, aGuidValue, aSubscriberCount, " + "aCreated, aModified, aCreator,aModifier) " + "VALUES (@RootObjectType,@EventType, @GuidValue, @SubscriberCount, " + "@Created, @Modified, @CurrentUserID,@CurrentUserID)" ); cm.AddInParameter("@GuidValue",DbType.Guid,_GuidValue); } cm.AddInParameter("@RootObjectType",DbType.Int16,(int)_RootObjectType); cm.AddInParameter("@EventType",DbType.Int16,_EventType); cm.AddInParameter("@SubscriberCount",DbType.Int32,nCurrentCount); //Standard fields cm.AddInParameter("@CurrentUserID",DbType.Guid, User.CurrentThreadUserID); cm.AddInParameter("@Created",DbType.DateTime, DBUtil.ToUTC(mCreated.Date)); cm.AddInParameter("@Modified", DbType.DateTime, DBUtil.ToUTC(DBUtil.CurrentWorkingDateTime)); DBUtil.DB.ExecuteNonQuery(cm,transaction); transaction.Commit(); } catch { // Rollback transaction transaction.Rollback(); throw; } finally { if(dr!=null) dr.Close(); connection.Close(); } }//end of using block }//end of dataportal_update method }//end of inner EventOfInterestManager class #endregion add events of interest / update subscriber count }//end of Outer NotifyEventOfInterestFetcherClass #pragma warning restore 1591 }//end Namespace