Friday 20 January 2012

CRM 2011: How to use Visual Ribbon Editor Tool?


Recently, I was assigned a task of ribbon customization in Dynamics CRM. The requirement was like configure a custom ribbon button on custom entity to call some JavaScript methods. I’ve used the Visual Ribbon Editor Tool. This tool is quite handy and intuitive for ribbon customization. I would like to share my experience here in below post.

Before to start with a Ribbon Editor Tool, let’s first configure the web resources (Images and JavaScript file).

The images will be used as an icon on a button. Below are 3 different types that CRM supports. Image formats can be PNG, JPG, GIF or ICO.
  1. Small: 16 x 16 pixels
  2. Medium: 32 x 32 pixels
  3. Large: 66 x 48 pixels

Following are the steps to add image to web resource
1. Click Web Resources on left navigation pane in your solution.

image

2. Click New to add web resource record.
3. Specify the name and the display name.
4. Select Format of the image.
5. Click browse to select an image path to upload image.
6. Save and publish the newly created web resource record.

image

Follow the same process to add 32x32 Image.
 
Let’s add a JavaScript function which will be called on custom button click
These are the steps to add new Library as web resource

1. Repeat steps 1-3 as above
2. Select Script(JScript) as Type of web resource.

image

3. Click on Text Editor.
4. Insert below function in Text editor window 


   1: function TestRibbon()

   2: {

   3:    alert("Test Ribbon Customization using Visual Ribbon Editor.");

   4: }



image

5. Click ok.
6. Save and publish a web resource

 
Now it’s time to play with Visual Ribbon Editor Tool. Use below link to download it. http://crmvisualribbonedit.codeplex.com/releases/view/75530

Extract the files and Run “VisualRibbonEditor.exe”

image

1. Click imageon top – left of the screen named as “Connection Info..” ,

image

2. Specify the connection details

image

3. Once connected, click on image button.


image


4. Select the required entity for ribbon customization.

image


5. By default, It Loads the ribbon type as Form

image

6. If you want to create a new Group then click on “New Group” button.

image


7. Specify the ID
image


Instead of creating new group, you could also add the button on existing group.For that you just need to select any existing group.

image

In this example I have created a new group. It will be added at the last position on ribbon toolbar.
image

8. Click on New Button to insert a button on above group.

image

9. Specify the button name.

image

10. Specify the following details for the newly created button on Details tab.

a. Id: Defines button id. 
b. Label: Defines caption or display text for button.
c. Tooltip: Defines tooltip text for the button.
d. Template Alias: Defines how button will be displayed on ribbon with Large, medium, small icon and it also vary depending on the selected Template of group.(step-7)

    • 01(Large) : Defines large image (32x32).
    • 02(Medium): Defines small image (16x16).
    • isv(Medium): Defines small image (16x16).

                 image










e. Sequence: Use arrow buttons to setup a sequence of custom button.
f. 16x16 Image: Name of button image from web resource (16x16).(Created as a web resource earlier)
g. 32x32 Image: Name of button image from web resource (32x32). (Created as a web resource earlier)

image

11. Now, click on Action tab shown as below.
12. Click on Add link for specifying the “Function name” and “Library”

image

You can also use “Display Rules” and “Enable Rules” via this tool which will allow us to configure many criteria for enabling/disabling a custom button.

13. Click on Save button that will import the solution in CRM

image

image

14. Now you can verify the button on your entity’s form ribbon.

image

15. On click of this button you’ll get the JavaScript alert Message.

image

Thursday 12 January 2012

Fragmented Index – Rebuild or Reorganize ?

Introduction
In past, many times I have written on Fragmentation of Indexes and how to Defrag them. You can find some related articles at -
After this, many of my readers have queried me for-
  1. What is the basic difference between ReBuild & ReOrganizing an Index?
  2. When to use what?
So, today I will address these two specific queries and also show a handy TSQL which could be used to remove Index fragmentation.
ReBuilding Index means the Index will be ReBuild from scratch using the same definition of its creation. It is same as using DBCC DBREINDEX. Please note that for new development do no use DBCC DBREINDEX as its deprecated from SQL Server 2005 onwards. It is generally preferred to rebuild OFFLINE. However, rebuild could be done ONLINE by specifying appropriate options.
ReOrganizing Index means the data at the Index leaf will be re-organized and the fragments will be removed to the max possible extent. It is same as using DBCC INDEXDEFRAG. Please note that for new development do no use DBCC INDEXDEFRAG as its deprecated from SQL Server 2005 onwards. ReOrganizing an Index is an ONLINE process.
When to use what – As per Microsoft, the recommendations are as under -
If Avg. Fragmentation < 5%, no action is required
else if 5% < Avg. Fragmentation <= 30%, reorganization is required
else if Avg. Fragmentation > 30%, rebuild is required
So, based on the above recommendations, the below TSQL could be used to serve the purpose -
USE DBName
GO
 
DECLARE @tsql NVARCHAR(MAX)  
DECLARE @fillfactor INT
 
SET @fillfactor = 70 
 
DECLARE @FragmentedIndexs TABLE (IndexID INT,
                                 IndexName VARCHAR(100),
                                 ObjectName VARCHAR(100),
                                 AvgFragmentationInPercent DECIMAL(6,2),
                                 FragmentCount INT,
                                 AvgFragmentSizeInPage DECIMAL(6,2),
                                 IndexDepth INT)
 
--Insert the Details for Fragmented Indexes.
INSERT INTO @FragmentedIndexs
SELECT 
  PS.index_id,
  QUOTENAME(I.name) Name,
  QUOTENAME(DB_NAME()) +'.'+ QUOTENAME(OBJECT_SCHEMA_NAME(I.[object_id])) + '.' + QUOTENAME(OBJECT_NAME(I.[object_id])) ObjectName,
  PS.avg_fragmentation_in_percent,
  PS.fragment_count,
  PS.avg_fragment_size_in_pages,
  PS.index_depth
FROM 
  sys.dm_db_index_physical_stats (DB_ID(), NULL ,NULL, NULL, NULL) AS PS
INNER JOIN sys.indexes AS I 
  ON PS.[object_id]= I.[object_id]
  AND PS.index_id = I.index_id
WHERE
  PS.avg_fragmentation_in_percent > 5  
ORDER BY 
  PS.avg_fragmentation_in_percent DESC
 
--Select the details.
SELECT * FROM @FragmentedIndexs
 
--Prepare the Query to REORGANIZE the Indexes
SET @tsql = ''
 
SELECT @tsql = 
  STUFF(( SELECT DISTINCT 
           ';' + 'ALTER INDEX ' + FI.IndexName + ' ON ' + FI.ObjectName + ' REORGANIZE '
          FROM 
           @FragmentedIndexs FI
          WHERE
            FI.AvgFragmentationInPercent <= 30
          FOR XML PATH('')), 1,1,'')
  
SELECT @tsql
PRINT 'REORGANIZING START'
EXEC sp_executesql @tsql 
PRINT 'REORGANIZING END'
 
--Prepare the Query to REBUILD the Indexes
SET @tsql = ''
 
SELECT @tsql = 
  STUFF(( SELECT DISTINCT 
           ';' + 'ALTER INDEX ' + FI.IndexName + ' ON ' + FI.ObjectName + ' REBUILD WITH (FILLFACTOR = ' + CONVERT(VARCHAR(3),@fillfactor) + ') '
          FROM 
           @FragmentedIndexs FI
          WHERE
            FI.AvgFragmentationInPercent > 30
          FOR XML PATH('')), 1,1,'')
  
SELECT @tsql
PRINT 'REBUILD START'
EXEC sp_executesql @tsql
PRINT 'REBUILD END'

Conclusion

To keep the indexes in proper shape, a timely defragmentation is necessary. When to defragment has got no THUMB RULE, it depends on the environment. However, the above script could be scheduled as per ones need to make sure that the indexes gets defragmented when need.

Friday 6 January 2012

Managing Timeouts while using System.Transactions in .Net

Problem
While working with System.Transactions in .net 2.0 or higher versions, we often come across a situation where we need to execute some long running processes inside Transactions and our process gets aborted after few seconds. This demands for some long running transactions. So, lets see how this can be achieved -
  • Setting the CommandTimeout for the Command object – Command object is used to execute raw TSQL/ Stored procedures though .net. This object has got a getter/setter property CommandTimeout which holds the wait time before terminating the attempt to execute the command. By default, the value is 30 seconds. So, a long running process will certainly get aborted after 30 seconds. In order to extend it over this time, we can set an appropriate timeout value. We need to set it to 0 (zero) to set it to infinite. For more information, please refer this msdn article.
  • Next important factor in this sequence is setting the timeout value for the TransactionScope. The TransactionScope class has got an overloaded constructor, where we can specify the timeout TimeSpan
    TimeSpan timeout = TimeSpan.FromSeconds(30);
    using(TransactionScope scope = new 8 TransactionScope(TransactionScopeOption.Required, timeout))
    {...}
    or we can also make use of the TransactionOptions.Timeout property and set its value.

TransactionOptions options = new TransactionOptions();
options.IsolationLevel = IsolationLevel.ReadCommitted;
options.Timeout = TransactionManager.DefaultTimeout;
 
using(TransactionScope scope = new 8 TransactionScope(TransactionScopeOption.Required, options))
{...}

By default, the value is 60 seconds. We can an appropriate value for this property or can also set it to infinite the same way as we did for the command object. We need to set it to 0 (zero) to set it to infinite.
This is the point where most of the developers think they are done after setting the timeout values for the command & the transaction objects. But this is not 100% correct. It holds true only to a time limit of 10 minutes. If you want your transaction to continue after that, setting only the above two values is not the solution. And here comes into play the TransactionManager settings.

TransactionManager sits on top of Transaction & Command. The default timeout value of TransactionManager is 10 minutes and it is defined in the machine.config file. The main problem in re-setting this value is -
  1. It can not be changed programmatically.
  2. And due to Point 1, we have to make manual changes in the machine.config file. This results in a machine wide change; i.e. all the applications running on that box will be affected by this change. So, one needs to take utmost care in doing so and should properly assess the consequences before attempting this change.
Please note that we can not specify the machinesettings in our own configuration file. But we need to actually add/change the machinesettings\timeout in the machine.config file. Below shows a timeout of 30 minutes after manual change.

<configuration>
 <system.transactions>
  <machineSettings maxTimeout="00:30:00" />
 </system.transactions>
</configuration>

Conclusion
The timeout of a transaction is decided by MIN(TransactionManager Timeout value, Transaction timeout value, command timeout value); i.e. a minimum value of these 3 settings is the deciding factor.

References
  1. http://social.msdn.microsoft.com/forums/en-US/windowstransactionsprogramming/thread/250b40b9-0838-4142-a8ff-d9d26690083b/
  2. http://social.msdn.microsoft.com/Forums/en-US/windowstransactionsprogramming/thread/7863f7e5-ec86-4f77-90e2-dc212ff099a2/