Subscribe to What I've learned working with Dynamics CRM 2011        RSS Feed
-----

Automatically (Re)Generating Early-Bound Entities

Icon 1 Comments
Welcome back to "What I've learned working with Dynamics 2011". Today we'll be talking about automatically generating and regenerating the code for early bound entities.

In case you haven't used it, the CRM 2011 SDK comes with several convenient tools, one of which is called CrmSvcUtil.exe. Now, if you have any familiarity with SvcUtil.exe you should already have a basic understanding of what this tool will do. Given some information as command line arguments, this tool will go out to CRM's Organization Service, download metadata about all entities, then uses that metadata to create classes that represent these entities.

The difference in using early bound entities vs. late bound entities is quite significant. For example, let's say we wanted to create a new account.

//late bound
var account1 = new Entity("account");
account1.Attributes.Add("name", "Account 1");
account1.Attributes.Add("emailaddress1", "account1@example.com");

//early bound
var account2 = new Account();
account2.Name = "Account 2";
account2.EMailAddress1 = "account2@example.com";


The confusion gets worse when dealing with entities you retrieved from the organization service. Does this entity have an attribute with this name? Do we have to check to see if it exists before we try to give it a value?

By using CrmSvcUtil.exe, you give yourself simple classes to work with.

Microsoft has provided a convenient instruction page on how to use CrmSvcUtil:

http://msdn.microsof...y/gg327844.aspx

I'll provide an example:

CrmSvcUtil.exe /url:http://hostname/orgname/XRMServices/2011/Organization.svc /out:CrmGeneratedTypes.cs /namespace:My.Namespace


Running that command from the Visual Studio Command Prompt will create a single code file that holds type information for all the entities in your organization. If you want to run it from the regular command prompt, you will either need to browse to the directory you installed the SDK at, or you will need to add the SDK's bin folder into your PATH variable.

However, there's a problem: what if you have lots of active development going on? You could be changing entities every day, or adding new entities, or deleting unused ones, or any matter of other work that will change your schema. You run the risk of unhandled runtime exceptions if you use code generated from old metadata.

So, what's the best way to make sure you can quickly and easily re-generate your code files? Well, I've found a simple solution that works if you're using Visual Studio: Pre-Build Command Line commands. If you've never used Pre- or Post-Build Command Line commands, you get to them by right-clicking a project file in VS Solution Explorer and clicking Properties. In the resulting window, choose "Build Events" from the left-navigation area, and you will see two text boxes, one for Pre-Build and one for Post-Build. These are commands that execute before and after the compiler does its work. They also allow us to use several handy macros. For example, the $(ProjectDir) macro expands out to the path of your project.

Let's start making your entities. First of all, the Pre-Build command line does not modify your PATH the way that Visual Studio Command Prompt does, so you must compensate for that. Either add your SDK's Bin folder to your PATH, or add the required files into a folder in your solution. A third option is to use the absolute path to the utility in your command, but that's brittle. If you're working on a team, you'd have to ensure that everyone puts the SDK in the same location on their disk. My suggestion is to choose one of the first options.

Now you need to prepare your command. I've already linked the detailed instructions and provided a simple example. Use those to create a command that will generate exactly what you want. Test that command by manually running it and verifying that the output conforms to your requirements.

Now that you have your command, you'll want to modify it slightly so that the file it generates appears in the correct location in your project. Here's an example command (this assumes you added the SDK\bin folder to your path):

CrmSvcUtil.exe /url:http://hostname/orgname/XRMServices/2011/Organization.svc /out:$(ProjectDir)CrmGeneratedTypes.cs /namespace:My.Namespace


Remember, the $(ProjectDir) macro expands to the full path of the project (trailing slash included). So in this example, the code file (CrmGeneratedTypes.cs) would be placed in the root folder of the project.

If you decided not to modify your PATH variable, these are the files you want to include in your project:

  • crmsvcutil.exe
  • crmsvcutil.xml
  • microsoft.xrm.client.dll
  • microsoft.xrm.sdk.dll


I suggest making a folder in your project called "CrmSvcUtil" and placing these files there.

Here's the command you'd use:

$(ProjectDir)CrmSvcUtil\CrmSvcUtil.exe /url:http://hostname/orgname/XRMServices/2011/Organization.svc /out:$(ProjectDir)CrmGeneratedTypes.cs /namespace:My.Namespace


Now, there's a fatal flaw in this plan that I haven't addressed yet: CrmSvcUtil.exe is not quick. I'm sure that the majority of your projects compile almost instantly, but this one will likely take minutes. There are two good options for handling this:

First, you can move this logic into a separate class library project. That's good practice anyway, because these entities will likely be useful to more than one project. Make a project dedicated to holding your entities. Then in your solution's Configuration Manager, you can uncheck the Build check mark for your project so that it's not built when the rest of the solution is. With this method, you can build your solution without slowing yourself down. Any time you want to re-generate your code file, you can right-click that project's project file and click Build. That will force that single project to compile, but it will run your Pre-Build Command Line commands first.

The other option is to use the REM command. REM makes comments in batch files. If you prefix your command with REM, it's the same as commenting it out. Now you can just uncomment the command any time you want the entities to be regenerated.

Easter Egg!

Not only can you do this with CrmSvcUtil, but you can do the same thing with SqlMetal.exe, which generates LINQ to SQL classes. You can point that at your OrgName_MSCRM database and generate a context to directly query your database. (Note: don't use this for inserts/updates/deletes, because directly manipulating data in CRM tables is not supported by MS).

Here's the command for that:
SqlMetal\SqlMetal.exe /views /code:$CrmDbTypes.cs /server:DbServerName /database:OrgName_MSCRM /namespace:My.Namespace /context:CrmDbContext /serialization:Unidirectional /pluralize


Follow the same advice to modify that command for use in the Pre-Build Command Line.

Thanks for reading! As always, feel free to request new topics in the comments section.

1 Comments On This Entry

Page 1 of 1

Curtis Rutland Icon

15 August 2013 - 08:31 AM
Notes on easter egg: SqlMetal.exe has no dependencies that aren't already part of the .NET Framework, so if you choose to copy it into a project folder, you just need the executable and its config file.
0
Page 1 of 1

Trackbacks for this entry [ Trackback URL ]

There are no Trackbacks for this entry

December 2014

S M T W T F S
 123456
78910111213
14151617 18 1920
21222324252627
28293031   

Tags

    Recent Entries

    Search My Blog

    0 user(s) viewing

    0 Guests
    0 member(s)
    0 anonymous member(s)

    Categories