(English) A Developer’s Comparisons Between Salesforce.com and MS CRM

mayo 6th, 2013

Disculpa, pero esta entrada está disponible sólo en English.

(English) Historical Page Navigation in Spotfire

abril 23rd, 2013

Disculpa, pero esta entrada está disponible sólo en English.

(English) Reorder data in a SQL Table

abril 8th, 2013

Disculpa, pero esta entrada está disponible sólo en English.

(English) QlikView Set Analysis vs. Load Script

marzo 22nd, 2013

Disculpa, pero esta entrada está disponible sólo en English.

CRM 2011: Deleting Items from a Managed Solution

marzo 5th, 2013

The ability to import and export CRM 2011 solutions is an extremely handy way to migrate additions and modifications between environments, so it’s sometimes easy to forget that not all changes are carried over with a solution. It seems natural that if an admin were to delete a field in environment A, that the exported solution would also delete that field in environment B upon import. However, this is not the case, as is plainly stated in the MSDN article, Introduction to Solutions:

Solutions can only add new solution components or overwrite existing solution components. Solutions cannot be used to delete solution components.

This isn’t normally an issue, since the admin can manually delete the field in environment B, provided that the solution was exported as Unmanaged. What if they exported it as a Managed solution, though? While this gives the admin the option to uninstall the solution from environment B, removing all the customizations it contained, it’s not possible to manually delete one of the imported fields. Uninstalling the solution and reinstalling a version without the field is an option, but this may result in data loss.

Currently, the best solution appears to be the one outlined in the (very appropriately named) MSDN blog article, Deleting things from a deployed CRM 2011 managed solution package. To summarize, the admin can create a second Managed solution in environment A with the same publisher and different name, that contains everything the original Managed solution does, sans the deleted element. Once they have installed this second solution to environment B, the admin can go ahead and safely delete the original solution. The system will see that both solutions have the same publisher and will not delete the elements held by the second solution.

The article goes into more depth, providing a thorough walkthrough and even example files so you can try it out yourself. It may not be an ideal approach, especially for vendors that are releasing their Managed solutions as products, but it appears to be the best option available for now.

Enabling/Using Package Configurations (SSIS)

febrero 13th, 2013

If you can accomplish all of your tasks with one SSIS package, I’m happy for you – but sometimes more than one is necessary. If you ever find yourself with multiple packages with similar properties (variables, connection managers, executables, etc.) it may be in your best interest to use a Package Configuration. This will save you some time down the road if you decide to create another package, or update properties of the existing ones. What a package configuration will allow you to do is make properties of the package external – saved as either an XML configuration file, environment variable, registry entry, or a few others. Once external, you can setup all or some of your packages to use the configuration – this way if changes need to be made, you can do so without having to update each and every package. In this post I will be creating a XML package configuration that contains my connection managers. Recently I did some SSIS cleanup for a client; they had 25+ packages, all containing the same connections. I recreated their database schema locally for testing purposes and enabled a package configuration in each package. By doing so, I was able to update the connection strings in my configuration file to use my local databases and make changes to the packages as needed. Upon completion I could simply change the connection strings back and deliver back to the client. At the same time, if the client ever moved their data to a different location, they could follow the same steps without having to edit any of their packages. The two connections I have are ‘Duck’ and ‘Goose’:
SS_1
To create a configuration, select Package Configurations from the SSIS dropdown on your menu bar:

SS_2
Check the box to enable package configurations, and click Add.

SS_3

For configuration type, select ‘XML Configuration File’. Make sure the radio button for ‘Specify configuration settings directly’ is selected and click Browse. Navigate to a common directory (I used C:\PackageConfigurations) and name your file ‘Connections.dtsConfig’, click Save.

SS_4

When you click Next you will be brought to a screen where you can select what exactly will be included in your configuration. As I stated before we are just going to add our connection managers. Check the box for each of your connections (or expand to select only specific properties), and click Next.

SS_5

Name your configuration, and click Finish. You’ve successfully created a configuration – your package is currently using it. So now let’s say you have another package that contains Duck and Goose connections, how do we set it up to use our new package configuration? Open the package and again click SSIS > Package Configurations. Make sure the ‘Enable Package Configurations’ checkbox is checked, and click Add. Browse to your configuration file, and click Next. When you select an existing configuration you will be prompted to either reuse or overwrite the file, click ‘Reuse Existing’. Click Finish, and then Close. Your package is now using the same configuration file – you can open the XML file in any editor and change the connection strings and it will be updated across all packages that use the configuration. Keep in mind this can be used for variables and executables as well, making the configurations even more flexible!

Calculate Age in JavaScript or C#

febrero 8th, 2013

A simple method to calculate age in years in both JavaScript and C# that avoids rounding up.  Additional info on the number of days in a year can be found here. JavaScript

function CalculateAge( birthDate )
{
    var msPerDay = 1000 * 60 * 60 * 24;
    var daysPerYear = 365.242199;
    var age = ( new Date() - new Date(birthDate) ) / msPerDay / daysPerYear;

    return age;
}

C#

public static double CalculateAge(DateTime birthDate)
{
    double daysPerYear = 365.242199;
    TimeSpan span = DateTime.Now.Subtract(birthDate);
    double age = span.TotalDays / daysPerYear;

    return age;
}

Tips for People New to QlikView

enero 24th, 2013

As someone whose background has been in development of business applications (specifically around Microsoft technology), when I started working with QlikView a ways back, it was a transition. Sure, you’re still building something using technology for end users, but it requires a different way of thinking. Here are some tips to keep in mind when starting with QlikView if you come from a traditional software development background.

  1. Learn that denormalizing your data isn’t a bad thing. As someone who has worked a lot with relational databases I always want to split things out into separate tables. With QlikView, because of the way data is stored and the internal compression routines, denormalizing data into fewer tables is often times a better idea. This is not true in every situation, but don’t be afraid to denormalize your data.
  2. Put as much as you can in your load script and not in formulas on objects. The load script runs when the data is loaded the first time whereas the formulas in objects are run every time a user makes a change to their selections or changes screens, which can slow things down.
  3. Use variables to represent the path to your QVD files. Surprisingly, I’ve seen a number of instances where when loading from multiple QVD files, the same path is included in each load statement. This becomes troublesome if you want to change the location of your QVD files because you’ll have to change it in multiple places. If you use a variable, you only have to change it once.
  4. You have to think about what you want to report on and keep in mind sometimes you need to report on what is NOT there. For example, let’s say you have a visualization where you report on the total items sold every Monday. For a few Mondays, though, there is no data in your source because that Monday was a holiday and the source doesn’t include zero values. You now have a gap in your data. Here is a good place to do something in your load script to include those zero values. Maybe you could create a master calendar (in the form of a table) of all Mondays and add it to your table, so every Monday has a value.
  5. If you control the source data, learn to think about the lowest level of data that you’ll need. Let’s say that you have a set of dashboards/visualizations with football statistics. What level do you need statistics for? Is it the totals by player for a game or do you need to get down to the play level? The difference here would be that if you only have totals for a game, you couldn’t look at a given players rushing yards in the 1st quarter vs. the 4th quarter across the season. If you have the play-by-play data, then you could track that information. Keeping this in mind can also be helpful to determine the best way to group data if using a group by statement.
  6. Comment your code. If you have any development experience, this should be nothing new. And don’t use comments like “Load the customer data.” That should be pretty obvious from the Load statement itself. Explain things that are unusual, tricky, or difficult. Explain why you’re doing something, not what you’re doing.
  7. Don’t try to do tricky things in formulas where you’re overriding the user’s selections or doing things that change what the user sees without them knowing that you’re doing something behind the scenes. It will confuse them.
  8. Clean up items in your load script. If you use a temp table, drop it as soon as you don’t need it anymore.
  9. Use friendly names for your fields. “Rate Effective Date” is much easier to read for a user than CUSTOMER.RATE_EFF_DATE. This will take you a bit more work, but you’re doing this for the users, not yourself.
  10. Don’t be too concerned if your load script takes a while to run (unless the time exceeds your reload schedule) because it only happens when you’re loading the data and your users won’t even see the load. Worry about performance if things take a long time when a user makes a selection.

Hopefully these will help someone as they get started with QlikView. Just like any other software, learning QlikView takes time. It can be especially daunting if you’re not used to working with BI tools but are used to software development.

(English) Telerik RadComboBox Visual Artifact in IE9 Compatibility Mode

enero 11th, 2013

Disculpa, pero esta entrada está disponible sólo en English.

CRM 2011 Plug-ins 101: Be Careful Where You Put That Service!

diciembre 13th, 2012

When I first started playing around with CRM 2011 plug-ins, I pretty much dove in headfirst to see what I could do. Sure, I browsed the SDK and modeled my code after the examples, but I ended up running into a nasty issue with one of my embellishments. What I thought was an innocuous method of handling the IOrganizationService proved to be problematic, considering how CRM 2011 plug-ins function.

I was creating the service like you usually do:

IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory = 
executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = 
serviceFactory.CreateOrganizationService(context.UserId);

Then I made a horrible mistake:

CrmData.Service = service;

At the time, I thought: “It sure is nice and clean, keeping all my data access methods in a separate class! Why don’t I just plop the service into some variable so I don’t have to pass it for each method call?” Little did I know that my choice to not RTFM would’ve told me exactly why I shouldn’t do that.

From MSDN’s Write a Plug-In article:

For improved performance, Microsoft Dynamics CRM caches plug-in instances. The plug-in’s Execute method should be written to be stateless because the constructor is not called for every invocation of the plug-in. Also, multiple system threads could execute the plug-in at the same time. All per invocation state information is stored in the context, so you should not use global variables in plug-ins or attempt to store any data in member variables for use during the next plug-in invocation.

The worst part about this is that it works great, up until you have the plug-in firing more than once, simultaneously. Various errors will be logged, from messages about the service already being in use to errors exclaiming that basic interal CRM functionality, such as RetrieveMultiple, cannot be found.

So, for anyone else out there who has a CRM 2011 plug-in that’s failing in strange and inconsistent ways, you may want to see if you’re keeping your IOrganizationService on a short leash. Sending it away to another class to be used indiscriminately by any ol’ plug-in execution is a surefire way to pad the server error logs!