Prevent user from overwriting the record CRM 2011 - dynamics-crm

I have a process that runs at specific time and updates records in "Open" state and disables them.
Recently I had a case when user opened the record almost at the same minute as the process was doing it's job. So while user was manually entering the data, process would already update the record and set record status to "Disabled". However, since user doesn't refresh the screen, when record saved, the status would change back to "Open" and wipe some data.
Any ideas on how this overwriting can be prevented?
P.S Process and the user should both have power to edit the record, but once it's disabled it should be locked somehow.

In crm 2011, not sure if the optimistic concurrency is available in any update rollups. But Optimistic concurrency using row version concept was introduced later in 2015 update 1.
You can implement similar approach, by querying the record again and verify the modifiedon between DB record & user modified record, then stop the execution & ask user to refresh to get latest data.

Related

Updating workflow status to cancelled in the MS Dynamics CRM AsyncOperationBase table with a SQL stored procedure, status not always persisting

I am currently diagnosing an issue with an implementation of MS Dynamics CRM 2013, whereby system jobs in CRM are programmatically cancelled soon after they have been created, if certain conditions in the application are met. However, these workflows have NOT cancelled, and continue processing - and I am wondering if this is due to the use of a SQL stored procedure to update the CRM database.
Here is the current (simplified) process:
Event in application triggers a CRM workflow, using the MS XRM OrganizationServiceProxy methods.
Something occurs in the application whereby we want to cancel the workflow that has recently been requested to start.
The "cancel workflow" request is saved, and picked up and processed by a custom application to process shortly after.
This application runs a stored procedure that finds the relevent AsyncOperation entry, and sets the ModifiedOn to getdate(), the StatusCode to 32 (Cancelled) and the StateCode to 3 (Completed).
Some time after succeeding to process the cancellation (as audited by our application), the workflow sometimes will continue to process, and the StatusCode/StateCode will no longer be 32 and 3. The modified DateTime in the AsyncOperation table will also be later than the application's "cancel workflow request processed" DateTime.
I've tried checking if the "StartWorkflow" request hasn't been processed by our application yet - but in every case, it has been sent to CRM before we attempt to stop it. So, CRM knows about the workflow, but updating the AsyncOperation table is not causing it to cancel. In many cases, the CreatedOn and/or ModifiedOn Datetime is AFTER we have attempted to stop the workflow, however, despite the start workflow request going to CRM before.
My main question is - is there a difference between sending a request to the OrganizationServiceProxy update AsyncOperation using:
workflow.Attributes["statecode"] = new OptionSetValue(3);
workflow.Attributes["statuscode"] = new OptionSetValue(32);
organizationServiceProxy.Update(workflow);
...versus a stored procedure that updates StateCode and StatusCode directly? I've read that it's usually a bad idea to update the CRM DB directly, but surely by retrieving asyncoperation from the organization service and then telling it to update specific columns, all it is doing is what the stored procedure would do? This is a CRM system with a high number of workflows being triggered and a lot of load, so I have a theory that it may be down to a workflow that's been triggered to start in CRM (but in a queued state) will NOT be in the AsyncOperation table until CRM picks it up... Which may explain that some of the entries have a "CreatedOn" date that is slightly later than the processed date of the request to STOP it. However, I'm not sure where workflows are stored in the DB when they are in a queued state, or if even they don't go to the AsyncOperation table instantly. I'm wondering if sending the request to CRM where it will probably run the same SQL that I am is a viable solution, or if anyone is aware of other elements that might cause a CRM workflow to continue to process and overwrite the StateCode/StatusCode despite having the statecode/statuscode set to cancelled/completed?
Due to load in production, any case where I can reduce abstraction and just directly affect the DB is not just welcome, but almost a necessity, due to timeouts and slow performance in CRM.
I see about 50 examples of this daily in production, so it's not isolated, but I cannot reproduce it in test environments... Which makes me believe moreso that it's a load issue, but whether CRM has additional steps when it updates a Statecode/Status code in the AsyncOperation table is my main concern. Thanks!
My main question is - is there a difference between sending a request to the OrganizationServiceProxy update AsyncOperation using:
workflow.Attributes["statecode"] = new OptionSetValue(3);
workflow.Attributes["statuscode"] = new OptionSetValue(32);
organizationServiceProxy.Update(workflow);
...versus a stored procedure that updates StateCode and StatusCode
directly?
There is a huge difference. Except for a very few exceptions such as creating custom indexes, reading from the Filtered Views, and adjusting certain settings, doing anything directly the Dynamics SQL database is unsupported, especially writing data directly to tables.
Outside of the very limited exceptions, everything MUST be done through the API (i.e. OrganizationServiceProxy which implements IOrganizationService). CRM is a message-based platform. If you write directly to SQL you circumvent its entire messaging system, with unpredictable and unsupported results.
In your scenario there is likely other stuff going on that your SQL stored procedure is unaware of. In short, you should implement whatever you're trying to achieve via the API, and get rid of all SQL writes to the CRM database.
Due to load in production, any case where I can reduce abstraction and
just directly affect the DB is not just welcome, but almost a
necessity, due to timeouts and slow performance in CRM.
While it is tempting to want to operate directly on the database, think of CRM as an API rather than a database.
With that in mind, you can work on performance analysis and optimization.
For starters, it might be helpful to analyze slow queries and add some indexes. And, since the Filtered Views enforce the security model at the database level, reading from them for any reporting or custom integrations might help.
It sounds like you have a long road ahead of you to get to a supported state.

Dynamics CRM Field Service: Unable to approve time off requests

I'm looking at the Field Service module of Dynamics 365. I'm trying to block out an employee's time on the schedule board by creating a time off request.
I can create the time off request, but as soon as the object is saved, the system automatically deactivates it.
The system will reported success when Approving a time off request but I can't see any changes in the data nor any records created in the audit summary. If I try to Active a time off request, the process fails due to a Business Process Error:
Microsoft.Xrm.Sdk.InvalidPluginExecutionException: Time off request records can't be reactivated.
To the best of my knowledge, there aren't any process changes to time off requests (but I'm unsure how to confirm this). From everything that I've read, this should be a fairly straight forward process so I'm not sure where to look next.
This page from the documentation is a good example of what I'm trying to do. It's failing on step 3 of "Approve a time-off request".
I've tried creating time off requests:
in the past
for tomorrow and more than 2 weeks future
of duration lengths from 2 hours through 2 weeks
for various user accounts
The time off requests are not conflicting with booked resources.
Any advice on what I could look into to determine if someone modified any processes / workflows associated with time off requests? Or is there something that I'm not doing that I should be?
I've learned that Microsoft's documentation is not complete and there was a bug.
Additional info on how Time Off Requests are used
There are two views of Time Off Requests (TOR) available to managers: Active and Inactive.
Active TORs: Lists TORs that a manager needs to approve
Inactive TORs: Lists TORs that have already been approved (i.e., the request itself has been dealt with)
Bookable Resources have a Time Off Approval Required property. When true, TORs created for the user are Active; when false, TORs created for the users are automatically moved to Inactive.
All Inactive TORs should appear as grayed-out boxes on the Schedule Board. If you attempt to Activate an Inactive TOR, the following error will correctly be reported:
Microsoft.Xrm.Sdk.InvalidPluginExecutionException: Time off request
records can't be reactivated.
Field Service Bug
Additionally, we experienced a bug that prevented Inactive TORs from being grayed out on the Schedule Board. I'm not sure if this was a process error or a client-side style issue.
We observed the bug in Field Service 6.1.0.1462. Upgrading to 6.2.1.38 resolved the issue and allowed Inactive TORs to show up on the Schedule Board.

EWS: Stop tracking changes while programmatically editing appointments

I'm editing Outlook appointments programmatically, synchronizing them with "appointments" of another software.
Next time my interface runs and I get the changelog, I don't want to get the changes I made programmatically on an Outlook appointment. Is there a way to stop tracking these changes?
Have you read the Filtered synchronization section in Mailbox synchronization and EWS in Exchange? I think the only way to ignore the changes your programmatic changes is to do a sync of user changes immediately before running your programmatic changes, then run your program, then do a SyncFolderItems repeatedly and discard the changes (don't do anything with them). That way, the next time you sync changes, you'll only get user created changes that you need to process.

Security Role Issue in CRM 2011 for Workflow on Custom Entity

I have a custom entity in CRM 2011 which a user can create an instance of.
When that instance is created, a workflow is kicked off which emails a user asking them to approve the instance.
The user gets the email and goes to the form for the entity where they mark it as Approved.
The workflow at this point is waiting for the Approval decision to be made (which it now is) but something to do with the users security role is blocking the workflow from proceeding. The workflow remains in a "waiting" status for the Wait Until.
If I do the same steps again but as an admin, it works correctly.
What permissions does the approving user need in order to not break the workflow?
I gave them Create/Write/Read to the entity, and WriteActivity, ReadQueue but it's not working
Any assistance would be greatly appreciated!
I'm afraid all I can offer is suggestions here:
Is the workflow actually still waiting on the wait until? Or has it failed and is in a waiting state? See if there is an error in the in the section at the bottom of the system job.
Who is the workflow actually running as? - have a look at the system job - I believe it will be the permissions of that user which are important.
Consider the business units here as well as the actual permissions granted, e.g. is the record owned by someone in a different business unit from the workflow owner?
If there is a permission missing you might be able to see which one in the in the crm trace logs, have a look at the async log.
Try granting the user the following permissions: Execute Workflow Job, Read & Write on System Jobs, Read on Process (you can always take them away later, if you find they are not required)
Did you confirm that workflow is published Organization-wide? It doesn't sound like that should be causing the problem, but I have run into that before.

How to save frequently used values without going through the database every time?

I am building a questionnaire, and i want to save the number of questions the user has completed and the number of questions available. I know how to calculate these values, but I don't want to run through the database, every time the user asks for a page that shows this information (which is quite often).
I considered saving it in the Session, but the problem is that the Session expires before the Authentication, so the information might get lost, but the user will still be logged in.
Any suggestions?
EDIT: I forgot to mention that i am working on a server, where i cannot specify the session timeout myself. Also, the number of answered questions has to be updated, when a user answers a question.
session's generally are extended each time a request is made to the server, so while someone is using the questionnaire, periodically send a request to the server using JavaScript just to ensure the session isn't ended.
You could consider increasing the session timeout.
A very interesing resource about caching and ASP.NET is http://msdn.microsoft.com/en-us/magazine/gg650661.aspx
As you can't specify the session timeout use the Cache class - it supports several different mechanisms for when to discard the cached item...
EDIT - as per comment:
With a cache you should implement a "write-through"-scheme - i.e. always update both, the cache and the DB which means the Cache is always right and any read never hits the DB after the initial load on application startup.
Another option is to update the DB and invalidate the cache item... on next read access you get a "cache miss" and handle that by hitting the DB and saving the result into the Cache... this way you hit the DB for reads in worstcase as often as for writes... this pattern only helps if you have much more reads than writes...

Resources