Skip to content

XRM-OSS/Xrm-Fluent-Query

Repository files navigation

XRM Fluent Query Build status NuGet Badge

Line Coverage Branch Coverage
Line coverage Branch coverage

This is a library for fluent query operations in Dynamics CRM / Dynamics365.

Requirements

This library can be used in CRM Plugins / Workflow Activities and in code of external applications. It is distributed as source file, so you don't need to merge DLLs. It does not include references / dependencies to any CRM SDK, so you can just install it and choose the CRM SDK that you need yourself. All CRM versions from 2011 to 365 are supported, just include the one you need to your project.

Remarks

This library sets the NoLock parameter on your QueryExpressions to true by default (plain QueryExpressions don't). This is a recommended best practice, as otherwise the records would be locked in the database before retrieval, which might result in decreased performance. Not locking the data before retrieval might result in dirty reads however, if the record has an update transaction executing at the same time. There's also a limit of how much concurrent locked queries can run concurrently. Find out more about NoLock here.

If you choose to lock the data for retrieval, set service.With.DataBaseLock().

Purpose

QueryExpressions add nice IntelliSense, however they tend to be quite verbose, which leads to poor readability. This fluent interface aims to make queries as short and readable as possible while preserving IntelliSense.

This could look something like this (When not developing early bound, you can simply leave out the generic parameter):

var records = service.Query<Account>()
                .IncludeColumns("name", "address1_line1")
                .Where(e => e
                    .Attribute(a => a
                        .Named("name")
                        .Is(ConditionOperator.Equal)
                        .To("Adventure Works")
                    )
                )
                .Link(l => l
                    .FromEntity("account")
                    .FromAttribute("primarycontactid")
                    .ToEntity("contact")
                    .ToAttribute("contactid")
                    .With.LinkType(JoinOperator.LeftOuter)
                )
                .RetrieveAll();

The equivalent QueryExpression for above fluent query would be:

var query = new QueryExpression
{
	EntityName = "account",
	ColumnSet = new ColumnSet("name", "address1_line1"),
	NoLock = true,
	Criteria = new FilterExpression
	{
		Conditions =
		{
			new ConditionExpression("name", ConditionOperator.Equal, "Adventure Works")
		}
	},
	LinkEntities =
	{
		new LinkEntity
		{
			LinkFromEntityName = "account",
			LinkFromAttributeName = "primarycontactid",
			LinkToEntityName = "contact",
			LinkToAttributeName = "contactid"
		}
	}
};

var records = service.RetrieveMultiple(query).Entities.Select(e => e.ToEntity<Account>()).ToList();

I believe the fluent syntax to be much easier to understand at first glance.

In addition to that, it automatically casts your entity objects if you call it with the generic parameter and implements automatic retrieval of all pages.

How to build it

If you want to build this library yourself, just call

.\build.cmd