Recurring Events and CustomSQL in ASP.NET

Dear Support,
I am only using the Timeline view in my scheduler. I am unable to get recurring event’s working in ASP.NET with ComplexSQL implemented on my adapter. I have implemented the Recurring events, my connector’s code is as follows:

        public override IdhtmlxConnector CreateConnector(HttpContext context)
        {
            dhtmlxSchedulerConnector connector = new dhtmlxSchedulerConnector(
                @"Select EventId, UserId, JobId, SE.SchedulerTypeId, FromDate, ToDate, EventName, EventDescription, " +
                      @"IsBillable, IsTentative, ApprovedUserId, ApprovedDate, CreatedUserId, CreatedDate, UpdatedUserId, " +
                      @"UpdatedDate, SchedulerType, IsJob, SchedulerColour FROM SchedulerEvents SE JOIN SchedulerTypes ST ON SE.SchedulerTypeId = ST.SchedulerTypeId"
                , "EventId"
                , dhtmlxDatabaseAdapterType.SqlServer2005
                , "Data Source=SERVER;Initial Catalog=DATABASE;User Id=Username;Password=Password;integrated security=False"
                , "FromDate"
                , "ToDate"
                , "FromDate as FromDate, ToDate as ToDate, EventName as text, EventId as EventId, UserId as UserId, JobId as JobId, SE.SchedulerTypeId as SchedulerTypeId," +
                    " EventDescription as EventDescription, IsBillable as IsBillable, IsTentative as IsTentative, ApprovedUserId as ApprovedUserId, ApprovedDate as ApprovedDate," +
                    " CreatedUserId as CreatedUserId, CreatedDate as CreatedDate, UpdatedUserId as UpdatedUserId, UpdatedDate as UpdatedDate, SchedulerType as SchedulerType," +
                    " IsJob as IsJob, SchedulerColour as SchedulerColour,rec_type,event_pid,event_length"
            );

            connector.Request.CustomSQLs.Add(CustomSQLType.Delete, @"DELETE FROM [SchedulerEvents] WHERE EventId = {EventId}");

            connector.Request.CustomSQLs.Add(CustomSQLType.Update, @"UPDATE  [SchedulerEvents] " +
              @" SET [UserId] = {UserId}," +
              @"     [JobId] = {JobId}," +
              @"     [SchedulerTypeId] = {SchedulerTypeId}," +
              @"     [FromDate] = '{FromDate}'," +
              @"     [ToDate] = '{ToDate}'," +
              @"     [EventName] = '{text}'," +
              @"     [EventDescription] = '{EventDescription}'," +
              @"     [IsBillable] = {IsBillable}," +
              @"     [IsTentative] = {IsTentative}," +
              @"     [ApprovedUserId] = null," +
              @"     [ApprovedDate] = null," +
              @"     [UpdatedUserId] = " + Common.Session.UserId + "," +
              @"     [UpdatedDate] = '" + DateTime.Now.ToString("yyyy-MM-dd HH:mm") + "'," +
              @"     [rec_type] = '{rec_type}'," +
              @"     [event_pid] = {event_pid}," +
              @"     [event_length] = {event_length}" +
              @"         WHERE EventId = {EventId}");

            connector.Request.CustomSQLs.Add(CustomSQLType.Insert, @"INSERT INTO  [SchedulerEvents] " +
           @"([UserId]," +
           @" [JobId]," +
           @" [SchedulerTypeId]," +
           @" [FromDate]," +
           @" [ToDate]," +
           @" [EventName]," +
           @" [EventDescription]," +
           @" [IsBillable]," +
           @" [IsTentative]," +
           @" [CreatedUserId]," +
           @" [CreatedDate]," +
           @" [rec_type]," +
           @" [event_pid]," +
           @" [event_length])" +
           @"   VALUES" +
           @"    ({UserId}," +
           @"    {JobId}," +
           @"    {SchedulerTypeId}," +
           @"    '{FromDate}'," +
           @"    '{ToDate}'," +
           @"    '{text}'," +
           @"    '{EventDescription}'," +
           @"    {IsBillable}," +
           @"    {IsTentative}," +
           @"    " + Common.Session.UserId + "," +
           @"    '" + DateTime.Now.ToString("yyyy-MM-dd HH:mm") + "'," +
           @"    '{rec_type}'," +
           @"    {event_pid}," +
           @"    {event_length})");

It seems as though If I do not choose to make the event recurring, the event_length field will be null, and the SQL statement will use {event_length} instead of 0 or null?

The event_pid is never getting a value, even if I choose to make the event recurring, it is always undefined?

I have reviewed the following document:
docs.dhtmlx.com/doku.php?id=dhtm … ntegration

And cannot figure out how to implement the following section of code in ASP.NET:

	function delete_related($action){
		global $scheduler;
 
		$status = $action->get_status();
		$type =$action->get_value("rec_type");
		$pid =$action->get_value("event_pid");
		//when serie changed or deleted we need to remove all linked events
		if (($status == "deleted" || $status == "updated") && $type!=""){
			$scheduler->sql->query("DELETE FROM events_rec WHERE event_pid='".$scheduler->sql->escape($action->get_id())."'");
		}
		if ($status == "deleted" && $pid !=0){
			$scheduler->sql->query("UPDATE events_rec SET rec_type='none' WHERE event_id='".$scheduler->sql->escape($action->get_id())."'");
			$action->success();
		}
 
	}
	function insert_related($action){
		$status = $action->get_status();
		$type =$action->get_value("rec_type");
 
		if ($status == "inserted" && $type=="none")
			$action->set_status("deleted");
	}
 
	$scheduler->event->attach("beforeProcessing","delete_related");
	$scheduler->event->attach("afterProcessing","insert_related");

I use the following JavaScript code to verify the values of these variables:

        scheduler.attachEvent("onEventAdded", function(event_id, event_object) { 
            // Recursion
            var rec_type = event_object.rec_type;
            var pid = event_object.event_pid;
            var event_length = event_object.event_length; 
            alert('rec_type: ' + rec_type);
            alert('event_pid: ' + pid);
            alert('event_length: ' + event_length);
        });

And also Place breakpoints in DataRequest.cs in DoInsertAction, DoUpdateAction and DoDeleteAction to read the SQL after it is generated and before it is executed against the database system, and I can see it is using {event_pid} in the query string no matter, and {event_length} if the event_length variable is undefined (not a recurring task). Below is the code I am using in the scheduler.config.lightbox.sections:

{ name: "recurring", height: 115, type: "recurring", map_to: "auto", button: "recurring"},

which was previously:

{ name: "recurring", height: 115, type: "recurring", map_to: "rec_type", button: "recurring"},

but only the rec_type variable was getting any values.
Any help to get this recurring event’s functionality working would be greatly appreciated.
Kind regards
Greg Goldberg

P.S.
not too sure if this is valid for the asp.net version of the code in schedulerConnector.ashx.cs

            connector.BeforeDataActionProcessing += new EventHandler<DataActionProcessingEventArgs>(onBeforeProcessing );
            connector.DataActionProcessed += new EventHandler<DataActionProcessingEventArgs>(onAfterProcessing);

        protected void onBeforeProcessing(object sender, DataActionProcessingEventArgs e)
        {
            if (e.DataAction.ActionType == ActionType.Deleted || e.DataAction.ActionType == ActionType.Updated)
            {
                this.Connector.Request.Adapter.ExecuteScalar("DELETE FROM SchedulerEvents WHERE event_pid='" + e.DataAction.Data[Connector.DecodeField("EventId")].ToString() + "'");
            }
            if(e.DataAction.ActionType == ActionType.Deleted && e.DataAction.Data[Connector.DecodeField("event_pid")].ToString() != "0")
            {
                this.Connector.Request.Adapter.ExecuteScalar("UPDATE SchedulerEvents SET rec_type='none' WHERE event_id='" + e.DataAction.Data[Connector.DecodeField("EventId")].ToString() + "'");
            }
            e.DataAction.SetCompleted();

        }

        protected void onAfterProcessing(object sender, DataActionProcessingEventArgs e)
        {
            var test = e.DataAction.Data[this.Connector.DecodeField("rec_type")].ToString();
            if (e.DataAction.ActionType == ActionType.Inserted && e.DataAction.Data[this.Connector.DecodeField("rec_type")].ToString() == "none")
            {
                e.DataAction.ChangeActionType(ActionType.Deleted);
            }
        }

In your sql query, rec_type,event_pid,event_length are not selected from database - so the recurring info will not be loaded at all ( it is expected that table in database has fields with such name )

And cannot figure out how to implement the following section of code in ASP.NET:
It is necessary only to work with recurring-exceptions, not necessary for default recurring events.
In any case, we will provide additional sample for .Net, in few days, which will show this part of functionality.

Hi Stanislav,
Thanks for pointing that out, had too add the fields a few times and thought I allready hit the select statement, but as you noticed, only hit the section field naming, update and insert statements within that scope of code.

Look forward to the sample.

Kind regards
Greg

Hi Stanislav,
Just to verify, on the following line of code, when a breakpoint is placed on the insert statement in DataRequest.cs:

Action.PostoperationalPrimaryKeyValue = this.Adapter.ExecuteScalar(sql);

On the private void DoInsertAction(DataAction Action) method (And most likely Update one too) statement look like this when they are being executed against the database (non recurring event):

INSERT INTO SchedulerEvents]
   ([UserId],
    [FromDate],
    [ToDate],
    [EventName],
    [EventDescription],
    [rec_type],
    [event_pid],
    [event_length])
        VALUES 
            (1,
           '2009-08-21 00:00',
           '2009-08-22 00:00',
           'New event',
           'Event Description',
           '',
           {event_pid},
           {event_length})

I can build default values into the table, or allow null values to be inserted on those fields, but the SQL statement itself won’t form correctly (even with a correct select statement). But is this caused because my onafterprocessing and onbeforeprocessing methods are incorrect?

Kind regards
Greg

It looks as a bug in .net connector and not related to your code.
Fixed version will be available on Monday.

Hi Stanislav,
I was wondering if you had managed to produce a solution to this issue?
Kind regards
Greg Goldberg

EDIT.

I was forming my SQL Statements wrong, it should have appeared as so:

     public override IdhtmlxConnector CreateConnector(HttpContext context)
        {
            dhtmlxSchedulerConnector connector = new dhtmlxSchedulerConnector(
                @"Select FROM SchedulerEvents SE JOIN SchedulerTypes ST ON SE.SchedulerTypeId = ST.SchedulerTypeId"
                , "EventId"
                , dhtmlxDatabaseAdapterType.SqlServer2005
                , "Data Source=SERVER;Initial Catalog=DATABASE;User Id=Username;Password=Password;integrated security=False"
                , "FromDate"
                , "ToDate"
                , "EventName as text, EventId as EventId, UserId as UserId, JobId as JobId, SE.SchedulerTypeId as SchedulerTypeId," +
                    " EventDescription as EventDescription, IsBillable as IsBillable, IsTentative as IsTentative, ApprovedUserId as ApprovedUserId, ApprovedDate as ApprovedDate," +
                    " CreatedUserId as CreatedUserId, CreatedDate as CreatedDate, UpdatedUserId as UpdatedUserId, UpdatedDate as UpdatedDate, SchedulerType as SchedulerType," +
                    " IsJob as IsJob, SchedulerColour as SchedulerColour,rec_type,event_pid,event_length"
            );

As the SQL statement is generated by the fields I have selected in the bottom 3 variables of the function, only noticed this today, when debugging the DataRequest.cs file in more detail.
Kind regards
Greg