1

Normally, I can query the class below like so:

this._xrmServiceContext.AccountSet.FirstOrDefault(x => x.Id == someGuid);

however, during compile time we don't know whether it is AccountSet, or AccountLeadSet, or 500 other queryables.

I would like to have functionality that will return a binding to XrmServiceContext, something like:

_xrmServiceContextBind.Where(var querable => iquerableName == name + "Set").FirstOrDefault(x => x.Id == someGuid)

the defintiion of XrmServiceContext is below:

public partial class XrmServiceContext : Microsoft.Xrm.Sdk.Client.OrganizationServiceContext
    {

        /// <summary>
        /// Constructor.
        /// </summary>
        public XrmServiceContext(Microsoft.Xrm.Sdk.IOrganizationService service) : 
                base(service)
        {
        }

        /// <summary>
        /// Gets a binding to the set of all <see cref="Xrm.Account"/> entities.
        /// </summary>
        public System.Linq.IQueryable<Xrm.Account> AccountSet
        {
            get
            {
                return this.CreateQuery<Xrm.Account>();
            }
        }

        /// <summary>
        /// Gets a binding to the set of all <see cref="Xrm.AccountLeads"/> entities.
        /// </summary>
        public System.Linq.IQueryable<Xrm.AccountLeads> AccountLeadsSet
        {
            get
            {
                return this.CreateQuery<Xrm.AccountLeads>();
            }
        }

        /// <summary>
        /// Gets a binding to the set of all <see cref="Xrm.ActivityMimeAttachment"/> entities.
        /// </summary>
        public System.Linq.IQueryable<Xrm.ActivityMimeAttachment> ActivityMimeAttachmentSet
        {
            get
            {
                return this.CreateQuery<Xrm.ActivityMimeAttachment>();
            }
        }

        /// <summary>
        /// Gets a binding to the set of all <see cref="Xrm.ActivityParty"/> entities.
        /// </summary>
        public System.Linq.IQueryable<Xrm.ActivityParty> ActivityPartySet
        {
            get
            {
                return this.CreateQuery<Xrm.ActivityParty>();
            }
        }

        /// <summary>
        /// Gets a binding to the set of all <see cref="Xrm.ActivityPointer"/> entities.
        /// </summary>
        public System.Linq.IQueryable<Xrm.ActivityPointer> ActivityPointerSet
        {
            get
            {
                return this.CreateQuery<Xrm.ActivityPointer>();
            }
        }
}

How do I query the AccountSet or ActivityPointerSet, or any other set, knowing only the name of the set during run time?

Alex Gordon
  • 57,446
  • 287
  • 670
  • 1,062

2 Answers2

2

Sounds like you're after .CreateQuery(), check out this sample (comes from from here):

var xrmServiceContext = new OrganizationServiceContext(_service);

var lstContact = (from c in xrmServiceContext.CreateQuery("contact")
where c["firstname"] == "Hugh"
select c).ToList();

foreach (var contact in lstContact)
{
   MessageBox.Show(contact["fullname"].ToString());
}

In your scenario, it would look like:

_xrmServiceContextBind.CreateQuery($"{iquerableName.ToLower()}").FirstOrDefault(x => x.Id == someGuid)
Alex
  • 23,004
  • 4
  • 39
  • 73
2

Although Alex provides the answer to your question, I have a fundamental issue with hacking together a LINQ Query that, IMHO, looks rather ugly, without providing the benefit of early bound type checking (don't get me wrong, I'm a big Earlybound fan. This just happens to be a case where you can't use it.).

If you're running CRM on Prem, or CRM online and you're willing to IlMege, than I'd recommend using the DLaB.Xrm Nuget Package (full disclosure, I wrote it). It gives you extension methods to write your query like so:

using DLaB.Xrm;

var entityLogicalName = getName();
var entity = this._xrmService.GetEntitiesById(entityLogicalName, someGuid).FirstOrDefault();

No really weird LINQ statement to write/maintain, just a single line that does what you want.

Community
  • 1
  • 1
Daryl
  • 18,592
  • 9
  • 78
  • 145