Over the years, this blog has been about many different things related to software development with Microsoft technologies. Since my current role focuses on PowerApps & Flow, that's what it's primarily about right now.
“I love early bound code because of compile time checking, LINQ query enablement, etc. I want to batch update a bunch of records, but OrganizationServiceContext.SaveChanges() executes under the hood as one web service call per entity. How do I batch update? Also, how do I make sure that only the fields I change are updated?”
The answer is that you basically have to combine your crmsvcutil.exe generated code with ExecuteMultipleResults. Here’s an example:
var conn = CrmConnection.Parse("USE A VALID connection string using appropriate format documented at https://msdn.microsoft.com/en-us/library/jj602970.aspx");
var ctx = new marcsctest1Context(new OrganizationService(conn));
// NOTE: The query below uses LINQ projection. The CRM LINQ provider will translate this to a query that only returns ID & Name
var query =
from a in ctx.AccountSet
select new Account
{
Id = a.Id,
Name = a.Name
};
var executeMultipleRequest = new ExecuteMultipleRequest()
{
Settings = new ExecuteMultipleSettings(){
ContinueOnError = false,
ReturnResponses = true
},
Requests = new OrganizationRequestCollection()
};
foreach (var account in query)
{
account.Name += " - Updated";
//UpdateObject is required to set the EntityState to Changed because it is readonly through crmsvcutil generated entities
I’ve been a longtime fan of LINQPad (www.linqpad.net) as a general purpose tool for executing LINQ queries with various LINQ enabled technologies as well as a general purpose scratchpad for testing out .NET code without having to fire up Visual Studio. I’ve already blogged about how to use LINQPad to work with the CRM Online SOAP service:
One thing that may not be obvious is how to use LINQPad to query the OData service that comes with Dynamics CRM Online. Using the same basic concept that I showed with the SOAP service, I created a video walkthrough of how to interact with the OData service from LINQPad:
Here’s the LINQPad starter code I showed in the video:
var clientId = "[YOUR_CLIENT_ID]";
var resource = "https://[YOUR_INSTANCE].crm.dynamics.com";
var redirectUri = new Uri("http://linqpad"); //replace with your redirect uri
var authContext = new AuthenticationContext("https://login.windows.net/common/oauth2/authorize", false);
var authResult = authContext.AcquireToken(resource, clientId, redirectUri, PromptBehavior.Auto);
Util.ClearResults();
var ctx = new marcsctest1Context(new Uri(resource + "/XRMServices/2011/OrganizationData.svc/"));
One of the things I did, after creating the video, was to write a reusable helper method in the LINQPad MyExtensions class so I can reuse the code to get the access token across multiple LINQPad query sessions. Here’s the code for the extension:
void Main()
{
// Write code to test your extensions here. Press F5 to compile and run.
}
publicstaticclass MyExtensions
{
// Write custom extension methods here. They will be available to all queries.
staticstring LINQPadAccessToken = null;
publicstaticstring GetAccessToken()
{
if (LINQPadAccessToken != null)
{
return LINQPadAccessToken;
}
var clientId = "[YOUR_CLIENT_ID]";
var resource = "https://[YOUR_INSTANCE].crm.dynamics.com";
var redirectUri = new Uri("http://linqpad"); //your redirect uri
var authContext = new AuthenticationContext("https://login.windows.net/common/oauth2/authorize", false);
var authResult = authContext.AcquireToken(resource, clientId, redirectUri, PromptBehavior.Auto);
Util.ClearResults();
LINQPadAccessToken = authResult.AccessToken;
return LINQPadAccessToken;
}
}
Here’s a version of the code in my query tab that is simplified, after writing and leveraging the helper method:
var ctx = new marcsctest1Context(
new Uri("https://[YOUR_INSTANCE].crm.dynamics.com/XRMServices/2011/OrganizationData.svc/")
Note the call to MyExtensions.GetAccessToken() above. You could obviously refactor the GetAccessToken() method more to make it even more reusable, but I will leave that as an exercise for you.
This approach will become even more powerful once Dynamics CRM introduces the new OData v4 service endpoint:
As I mention in the video, once that happens, you’ll want to perform the codgen with the OData Client Code Generator instead of “Add Service Reference”:
I recently discovered that the LINQPad Plugin for Microsoft Dynamics CRM 2011 doesn’t support authenticating using Office 365 credentials. According to commenter EdWells, you can copy the latest version of crmsvcutil.exe and microsoft.xrm.sdk.dll over the version that ships with the LINQPad plugin as a workaround. However, this didn’t work for me. Have no fear, LINQPad allows you to reference external dlls. So I just manually ran crmsvcutil.exe, compiled the output into an assembly using Visual Studio, and then referenced the dll + appropriate dependent assemblies.
You add References/Imports via the properties dialog:
MsftIanImportTest.dll is the assembly I put the crmsvcutil.exe code in.
Here’s a basic example to get it all wired up:
UPDATE: I use LINQPad as a way to do things like update multiple records, etc. I have a tip to improve execution time performance here.
UPDATE: There’s a known issue with the LINQPad Plugin for Microsoft Dynamics CRM 2011 and Office 365 authentication. I cover a workaround here.
Using FetchXML is necessary in many situations with CRM 2011. Using FetchXML becomes even more necessary if you are taking a “design for online” approach to solution building. I’m a big believer that everyone should approach solution design this way because then your solution will truly be portable between CRM Online and CRM OnPrem (i.e. the CRM you install yourself). Typically, the need for FetchXML shows up first when you are building custom SQL Server Reporting Services (SSRS) reports. That’s because FetchXML based reports are the only option in CRM Online. I mentioned in my CRM Online myth busters post that I prefer to use LINQPad + LINQPad Plugin for Microsoft Dynamics CRM 2011 to compose my queries, then convert them to FetchXML. This post is a walkthrough of how I do it. I got the inspiration for the code sample I will present from the following two samples:
Place the code I provide you below within the MyExtensions class under the comment that says to “write custom extension methods here.” Here’s what the file looks like before you’ve added anything to it:
void Main()
{
// Write code to test your extensions here. Press F5 to compile and run.
}
publicstaticclass MyExtensions
{
// Write custom extension methods here. They will be available to all queries.
}
// You can also define non-static classes, enums, etc.
Here’s the code you need to add under the comment:
In addition to adding the code, you need to add references to a few .NET assemblies. From within the “My Extensions” file, press the F4 key to bring up the properties dialog. Add references to the following assemblies (note your location for CRM 2011 SDK assemblies might be different):
Now, once you’ve written and executed the query that you want in LINQPad:
…you can then wrap the query in parenthesis and call the ToFetchXml() extension method to get the FetchXML:
BAM! This approach has really helped me be productive in composing FetchXML queries. I use this mostly when writing SSRS reports, but also find it useful for other occasions where I need to use FetchXML. See the LINQ Limitations section of the Use LINQ to Construct a Query documentation for more details.
Yesterday, I blogged about a solution to compose OData / WCF Data Service queries using LINQ for situations where LINQ enabled client libraries don’t exist (i.e. JavaScript and Windows Phone 7).
The post is all about using LINQPad as a tool to write your LINQ queries, then using the feature in LINQPad that gives you the url query translation. Well today, a new MSDN Code Callery project just popped up called OQuery that offers another approach that doesn’t require using an external tool such as LINQPad:
“OQuery is a library which gives you a fluent style interface for building OData Url Fragments in javascript or C#. Neither Javascript or Silverlight for WP7 support LINQ and so this library in those cases.”
The major caveat (and bummer) with the library is that “LINQ support in the client library has been removed as the core support is not yet available on the phone platform.” I have a tip/trick for LINQ lovers like me that will allow you to still use LINQ query syntax to compose your query (kind/sorta). A tool I find useful to when writing OData queries on Windows Phone 7 is LINQPad. I use the tool to write LINQ queries against my data service, then get the url syntax query translated for me:
Once I get my LINQ query right, I just paste the http string into my app. I’m still surprised about how many people aren’t aware of LINQPad. You must check it out if you use LINQ in your day to day coding (which I am sure most of you do now). You can learn more about using LINQPad against OData services (amongst many other uses) from the product site:
NOTE: This tip/trick is very useful when querying OData services from JavaScript as well. Here are two helpful posts on using jQuery to interact with an OData service:
With the .NET Framework 3.5 (the version native to Visual Studio 2008) coming up on its first anniversary, Microsoft is poised to release the first update to the framework in the form of Service Pack (SP1). This Service Pack is unlike your standard Service Pack, in that it will introduce new features/capabilities to the .NET Framework. Some of these features where originally planned to be in the initial release of the framework and others are features/capabilities added to enhance or further secure the core .NET Framework. The August Developer Dinner is going to focus on some of the new features as well as a few of the new enhancements, to give you an introduction of the improved capabilities of the Microsoft Developer Platform.
What you will learn:
This evenings presentation will be a running stream of demonstration focusing on new features and functionality coming in the new Service Pack for several of the key areas of .NET Development today, including Web Development (ASP.NET), Database Development (ADO.NET), Web Services/SOA (Windows Communication Foundation) and User Experience (Windows Presentation Foundation).
You will see demonstrations that will include:
Making data access easier with the ADO.NET Entity Framework.
Exposing your data access layer using ADO.NET Data Services
Building “Data Entry” Web-based applications faster than ever using ASP.NET Dynamic Data.
Making AJAX Applications faster with script combining and easier with built in support for handling browser history (i.e. back/forward buttons).
How to achieve up to 40% faster startup performance for your WPF applications and further improve the startup experience using a splash screen.
Reducing the time it takes to deploy your WPF applications using the New .NET Framework Client Profile.
Normally, I make my actual demo code available for download. However, this time around, my demo code was based on the .NET 3.5 Enhancements Training Kit. I blogged about it here:
Looking for free introductory training on the .NET 3.5 SP1 & ASP.NET MVC? Head over to Jonathan Carter’s blog to get all the details on the .NET 3.5 Enhancements Training Kit RTM. What will you find? Information and links to download a kit that has presentations, demos, and labs covering what’s new in ASP.NET AJAX, ASP.NET Routing, ASP.NET MVC, ASP.NET Dynamic Data, ADO.NET Data Services, ADO.NET Entity Framework, WCF, and Visual Studio 2008 SP1. If you’ve seen any of my 3.5 SP1 or my older "ASP.NET Futures" presentations, then you are already familiar with some of the content in the kit. I used an early release of the kit as the foundation for some of my demos. The kit has come a long way since I used it. I skimmed through everything last week. There is lots of good content in here!
In this screencast, I build off of the concepts shown in my previous screencast and show you how to render a polygon on a Virtual Earth map using REST, Windows Communication Foundation (WCF), LINQ to SQL, and the new geography data type in SQL Server 2008.