Waiting/Timed Workflow VS Windows Service

Developing some service or workflow to handle some periodic tasks is natural to CRM solutions. Last week, I have been looking for the best way to handle periodic tasks like sending reminders, creating tasks based on date/time, birthday notifies etc.

So I have an entity project schedule and I have thousands of records of this entity where I have to send email reminders. For each record I can have a waiting workflow. So I can have thousands of waiting workflows. While, I can develop a windows service that runs overnight and process records according to criteria and send reminders.

What about performance constraints for hundreds of waiting workflows VS one windows service instance running overnight?

So here are some merits and demerits for both techniques:

1. Workflows can be configurable with no code but we need to create a configuration mechanism for windows service and scheduled tasks.

2. We can control the best time to execute a windows service while workflows fired on the event matching time condition.

3. Any change in the logic can be rolled out with ease in case of windows service during off peak time while waiting workflow remain in waiting as per old logic. So it creates a big issue in case of maintenance.

4. If number of records is high then creating waiting workflows cause a strain on the system and degrade performance as compared to windows service.

5. If there is frequent update operation on the waiting workflow entity then every time a change occur workflow becomes active and then in waiting state. This can cause a strain to the live system.

Although waiting workflows will not consume any CPU or memory resources but overhead of handling change and strain on system during peak hours make them a less favorite as compared to windows service. Personally I feel much control and maintainability in windows service as compared to workflows.

Announcing 2nd Microsoft Dynamics CRM Incubation Week

Microsoft Dynamics CRM Incubation Week is designed to offer following assistance to entrepreneurs.

 

- Learning and building next generation business solution on Microsoft Dynamics CRM Platform (a rapid application development platform to reduce the cost and Go-To-Market time) with help of on-site advisors (Microsoft Dynamics CRM experts).

- Getting entrepreneurs coaching from a panel of industry experts (academic and angel investors)

- Generating marketing buzz for their ideas

 

The 2nd CRM Incubation Week is being held at Microsoft Technology Center, Boston, MA from Mon 4/20/2009 to Fri 4/24/2009. This event consists of ½ day of training, 3 ½ days of active prototype/development time, and a final day for packaging/finishing and reporting out to a panel of judges for various prizes.

 

This event is a no-fee event (plan your own travel expenses) and each team can bring 3 participants (1 business and 1-2 technical). To nominate your team, please submit the following details to Sanjay Jain. Nominations will be judged according to the strength of the founding team, originality and creativity of the idea, and ability to leverage CRM as a Platform.

 

 

Organization Details

Name

 

Web Site URL

 

Mailing Address

 

Solution Overview

 

Target Industry

 

 

Team Details

Participant 1:

 

Name

 

Brief BIO

 

Email

 

Phone

 

Participant 2:

 

Name

 

Brief BIO

 

Email

 

Phone

 

Participant 3:

 

Name

 

Brief BIO

 

Email

 

Phone

 

 

Synchronous Matchcode Generation – Duplicate Detection in Dynamics CRM 4

Microsoft Dynamics CRM 4.0 provides a Duplicate Detection feature to protect the quality of your data. Duplicate Detection rules can be defined for different record types, including custom entities, and can be defined across record types as well.

In background a matchcode service is running and creating/updating matchcode for new/existing records. This matchcode will be matched to detect duplicates. Matchcode service runs asynchronously after 5 minutes and create/updates matchcode. So any record that is inserted within 5 minutes of time will not be detected. This happens only when you insert record within less than 5 minutes of time or before generation of matchcode. This results in no warning message for duplicate records even though duplicate record exists according to duplicate rules.

There is no way to persist matchcodes synchronously when records are created/updated through the UI, without writing extra code. So here are few recommendations to do so.

  1. A workaround is to Import data (Tools->Import), and choose the option to prevent creation of duplicate records. This will create the matchcodes for all imported records synchronously.
  2. You can force the creation of a matchcode at the time of record create/update by including the PersistInSyncOptionalParameter in the Create/Update request and setting its value to ‘True’. A code snippet that includes the optional parameter in a CreateRequest is as follows:
    CreateRequest request = new CreateRequest();
    request.OptionalParameters = new OptionalParameter[] { new PersistInSyncOptionalParameter (true) };

  3. You can write a plugin for this at Create and Update message. Beware to silent your plugin by setting Context to null.

if (context.Depth <= 1)
                {
                    if ((message.ToLower() == “create”))
                    {
                        DynamicEntity entity = (DynamicEntity)context.InputParameters.Properties[ParameterName.Target];

                        TargetCreateDynamic createdynamic = new TargetCreateDynamic();
                        createdynamic.Entity = entity;                      

                        CreateRequest request = new CreateRequest();
                        request.Target = createdynamic;
                        request.OptionalParameters = new OptionalParameter[] { new PersistInSyncOptionalParameter(true) };

                        CreateResponse response = (CreateResponse)service.Execute(request);
                    }
                }
                context = null;

File Attachment to Notes – Dynamics CRM 4.0

In Dynamics CRM 4.0, file attachment to entities is pretty simple as compared to CRM 3.0. UploadFromBase64DataAnnotationRequest and UploadFromBase64DataAnnotationResponse object are both deprecated. Instead a new attribute has been introduces in annotation object with documentbody that accepts string in base64 encoding. Please find the below sample:

 

Reading file data into Byte array and then converting it to base64. Since I am using in memory object of StringBuilder class so I have just used str.ToString() to return string.

 

Byte[] data;

 ASCIIEncoding encode = new ASCIIEncoding();

data = encode.GetBytes(str.ToString());

string b64 = Convert.ToBase64String(data);

 

Next, simply create the annotation entity and set the attributes as below:

annotation note = new annotation();           

           

note.subject = “Test Export”;

note.filename = “exported.txt”;

note.mimetype = “text/html”;

note.documentbody = b64;

 

note.objectid = new Lookup();

note.objectid.type = “new_export”;

note.objectid.Value = entityid;

note.objecttypecode = new EntityNameReference();

note.objecttypecode.Value = “new_export”;

                       

Guid annotationId = service.Create(note);

 

Auto Numbers in MSCRM

Last week I have been looking for the best approach to use auto numbers in Microsoft Dynamics CRM. After discussion with my peers I have come to the following possible options that can be used for auto numbering. Although these may not be the efficient techniques to get auto number work in CRM but they are all workable solutions.

Option 1:

Very simple, supported and mostly acceptable way of auto numbering is to read the attribute Max value and then add 1 to get next auto number. For example you have a custom entity named Project and you want to auto number Project_Ref_Number attribute.  But do not retrieve all records. Just retrieve the record with maximum number value by using following two properties of PageInfo Class in SDK and set descending order.

PageInfo.Count = 1;
PageInfo.PageNumber = 1;

One more consideration should be taken in account to register your auto number plugin to at PreCreate rather at PostCreate.

Issues:

In multi-user environment, this approach can come up with duplicate numbers in Project_Ref_Number when more than one user is creating project records.

Option 2:

This technique requires a bit more work but still supported way of doing things and all the time you will be getting 100% unique number.

You need to create a new table for project entity in a different database and not in CRM default database.

create table dbo.ProjectNumbers
(
 Project_Ref_Number int identity(1,1) primary key clustered,
 Projectid uniqueidentifier not null
)
go

Create a stored procedure for inserting a record into new database. This will increase the performance of your insert query.

create procedure dbo.proc_new_ProjectNumber

@ProjectId uniqueidentifier,

@Project_Ref_Number int output

as

insert into dbo.ProjectNumber

(

 ProjectId

)

values

(

 @ProjectId

)

select @Project_Ref_Number = scope_identity()

go

 

In your Plugin/Callout:

1.   Access you database using ADO.NET

2.   Execute stored procedure and get next number from returned results

3.   Set the value of the returned number to target entity attribute approperiatly.

4.   All Done

Issues:

1.   You have to setup database.

2.   You have to read and insert into external database.

Option 3:

This option used a lock mechanism on a text file placed somewhere at your webserver. You can create one file to store next number for all entities or you can create one file for each entity. In your Plugin/Callout:

1.   Put a lock on file.

2.   Read the file and read the number there.

3.   Update the number by adding 1.

4.   Release the lock.

5.   Use this number and set your target entity attribute appropriately.

string ProjectAutoNumber = “FilePath”

lock(this)

{

                                       

TextReader textReader = File.OpenText(ProjectAutoNumber);

AutoNumber = textReader.ReadLine();

textReader.Close();

AutoNumber = (long.Parse(AutoNumber) + 1).ToString();

TextWriter textWriter = File.CreateText(ProjectAutoNumber);

textWriter.WriteLine(AutoNumber);

textWriter.Close();

}

 

Issues:

1.   Resource locking

2.   File system Read/write cost

Although all these options work well but I am still looking for some more robust solution. Ideally I am looking for something like GUID. GUID’s are instantly available and 100% unique.

For your suggestions and improvements, please comment.