简体   繁体   中英

CRM Linq query for Incidents - Invalid where condition

The Code:

var site = CrmRepository.QueryFor<Account>()
                .Where(a => a.iss_OperatorSiteId == OperatorSiteId.ToString())
                .FirstOrDefault();
SiteCases = CrmRepository.QueryFor<Incident>()
                    .Where(i => i.AccountId.Id == site.Id
                                && (i.iss_Status != new OptionSetValue(
                                      (int)StatusOptionSet.Closed) 
                                   && i.iss_Status != new OptionSetValue(
                                      (int)StatusOptionSet.PendingFinalization))
                                || (i.iss_ResolutionDate == null 
                                    || i.iss_ResolutionDate > 
                                          DateTime.Today.AddDays(-30))
                                || (ShowFullCaseHistoryBox.Checked))
                    .AsEnumerable()
                    .Select(i => new CrmCaseListItem(i))
                    .ToList();

The Details:

  • CrmRepository is a wrapper for the CRM Linq context generated by CrmSvcUtil, adapting it to a common IRepository interface in use for other data stores. The QueryFor<Incident>() call is equivalent to a CreateQuery<Incident>() call on the context itself.

  • iss_Status is an "Option Set"-type property. StatusOptionSet is an enum meant to simplify use of the option values in code.

  • iss_ResolutionDate is self-explanatory, and included instead of referencing the Case Resolution record for simplicity, and because, in our workflow, a Case isn't actually "resolved" until the problem has not only been solved, but the Case record and related records have been processed and audited, so for SLA obligations we need to know when the problem was solved separately from when the Resolution was applied to fully close the case.

  • The basic idea is to show Incidents (which we call Cases) associated with a specific account that are either in an open Status, or have been closed (resolved) in the last 30 days, or the user wishes to see the full history (in which case all Cases, open or closed, are retrieved).

  • ShowFullCaseHistoryBox is a Winforms checkbox; when checked, the full Case history for the Account should be retrieved.

  • CrmCaseListItem is a DTO used as the backing for a DataGridView; it takes the Incident in its constructor and exposes properties shown on the Grid.

The Error:

Invalid 'where' condition. An entity member is invoking an invalid property or method.

The Question:

What am I trying to do that's invalid? The first clause, matching the Account IDs (and thus requiring a projection), worked fine by itself, so I must assume it's one of the others, but I can't determine which. The properties of the Incident being examined aren't projected or manipulated, which is the usual no-no for Queryables, so I'm really at a loss here.

The EDIT (which has been edited again):

After running it through some tests to evaluate each individual clause, using a few of the suggestions so far and plugging all the known good elements of the clause back together, here's the closest thing that works:

var site = CrmRepository.QueryFor<Account>()
                .Where(a => a.iss_OperatorSiteId == OperatorSiteId.ToString())
                .FirstOrDefault();
SiteCases = CrmRepository.QueryFor<Incident>()
                .Where(i => (i.AccountId.Id == site.Id) &&
                       (
                           (i.iss_Status.Value != (int) StatusOptionSet.Closed
                            && i.iss_Status.Value != (int) StatusOptionSet.PendingFinalization)
                           || (i.iss_ResolutionDate != null
                               && i.iss_ResolutionDate.Value > DateTime.Today.AddDays(-30))
                       //|| ShowFullCaseHistoryBox.Checked
                       )
                )
                .AsEnumerable()
                .Select(i => new CrmCaseListItem(i))
                .ToList();

The only thing that's still not functioning is the check of the CheckBox to show full case history (basically overriding either of the previous two clauses about Status or Resolution Date). It doesn't work as is (uncommenting the inline expression) or if it's extracted into a variable. Everything else seems to work as expected. This feature was optional so if it just won't work at all, no way, no how, then I'll break it to the client gently, but I'd really like this to work as I'm just so close. Any thoughts?

LINQ to CRM has to be converted into Query Expressions. When dealing with query expressions, you have to use the int value of the option set value. Try calling .Value on your option set properties, and just casting your enums to the intended value to see if that resolves your issue.

You could also use the Early Bound Generator , which creates Early Bound Enum Properties on your entities. Then you wouldn't have to cast the enums to ints, and wouldn't have to put .value in there as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM