delegateas/XrmContext

Generate attribute names as string constants

Closed this issue · 5 comments

It would be very nice if XrmContext also generated attribute names as string constants. Such constants are useful when referencing attribute names in query expressions or column sets.

Here is a simple example with a late-bound Account entity:

var account = new Entity(Account.EntityLogicalName);
account["telephone1"] = "12345678"; // Option 1: Magic string is error prone.
account[nameof(Account.Telephone1).ToLower()] = "12345678"; // Option 2: No magic string, but you still might forget ToLower.
account[Account.telephone1Attribute] = "12345678"; // Option 3: What I am hoping for. :)

This has already been done for CrmSvcUtil, but I would prefer not having to use more than one tool (XrmContext) when generating early-bound entity classes.
https://xrmpalmer.wordpress.com/2013/08/23/crmsvcutil-attribute-constant-generator-extension/

Can you elaborate on what the use case is for this is? The above example would be better by simply writing it using early bound.

As I mentioned, the use case is query expressions:

var query = new QueryByAttribute(Account.EntityLogicalName);
query.AddAttributeValue("telephone1", "12345678"); // Account.telephone1Attribute would be better.
var accounts = _service.RetrieveMultiple(query);

Or column sets:

var columnSet = new ColumnSet("name", "ownerid"); // Account.nameAttribute, Account.ownerIdAttribute would be better.
var account = _service.Retrieve(Account.EntityLogicalName, _accountId, columnSet);

The late-bound code was quick to write, but you're right that it wasn't a good example.

Why can't these two examples be written early bound using the LINQ provider (i.e. what is the use case)?

The underlying assumption from my side is of course that early bound is better. We are so convinced about this that it permeates the decisions made when developing our tools. We have no plans of making it easier to write late bound code (but I am curious as to why you think it is necessary).

I agree that using LINQ is preferable. However, I do occasionally use QueryExpression for certain queries that benefit from the NoLock hint. Unfortunately, this is not available via LINQ as far as I know.

OK. I have never written CRM-code that needed the NOLOCK hint (maybe the code could be optimized?).

Another thought could be to write your strongly typed code in LINQ and then convert to to Query Expression: Convert Linq expression to QueryExpression or FetchXML (though I have not tried this myself or have any idea how robust that conversion code would be).

If you want to move forward with using late bound code, the Latebound Constants Generator is probably helpful. Otherwise feel free to make a pull request for XrmContext.

Just to make it clear, we would recommend writing your two examples as follows:
Example 1:

using (var context = new Xrm(OrganizationService))
{
    var accounts = context.AccountSet.Where(a => a.Telephone1 == "12345678");
}

Example 2:

var account = Account.Retrieve(OrganizationService, _accountId, a => a.Name, a => a.OwnerId);