Nullable filters in XRM where clause

为君一笑 提交于 2020-01-05 06:38:38

问题


I'm using the XRM (early bound) types in a WCF project so I have access to the CRM model and can use LINQ queries. But I've been running into a problem described here, it's the limitations on the where clause specific to XRM LINQ:

where [clause limitations]

The left side of the clause must be an attribute name and the right side of the clause must be a value. You cannot set the left side to a constant. Both the sides of the clause cannot be constants.

Supports the String functions Contains, StartsWith, EndsWith, and Equals.

One requirement that keeps popping up is when a parameter is null, all entities should be returned otherwise filter by the parameter. But I can't think of a way to do this without breaking the requirements above, or writing multiple queries to handle the scenario when it's null.

this is an example of one of my queries, the typeFilter == null is the problem here is I've used a constant on the LHS. In my real code there's a guard clause that points typeFilter == null to another query but I now have to add a start/end date filter (both nullable) and I cannot express how much I don't want to write a query for every combination of nullables.

private IQueryable<EventInfo> getAllEvents( DataContext context, EventType? typeFilter )
{
    return (
        from evt in context.new_eventSet
        where
        ( evt.statecode == new_eventState.Active ) &&
        ( typeFilter == null || evt.new_EventType.Value == (int) typeFilter.Value )
        select new EventInfo()
        {
            ID = evt.Id,
            EventType = (EventType) evt.new_EventType.Value
            ...
        } );            
}

回答1:


How about:

if (typeFilter == null)
{
        return (
        from evt in context.new_eventSet
        where
        ( evt.statecode == new_eventState.Active )
               select new EventInfo()
        {
            ID = evt.Id,
            EventType = (EventType) evt.new_EventType.Value
            ...
        } );   
}
else
{
        return (
        from evt in context.new_eventSet
        where
        ( evt.statecode == new_eventState.Active ) &&
        evt.new_EventType.Value == (int) typeFilter.Value )
        select new EventInfo()
        {
            ID = evt.Id,
            EventType = (EventType) evt.new_EventType.Value
            ...
        } );   
}



回答2:


I've answered my own question! sometimes you just need a place to vent your problems before you get it.

the trick was to not use LINQ syntax:

private IQueryable<EventInfo> getAllEvents( DataContext context, EventType? typeFilter, DateTime? startDateFilter, DateTime? endDateFilter  )
{
    var result = context.new_eventSet
        // active records
        .Where( evt => evt.statecode == new_eventState.Active )             
        // is publish-able
        .Where( ..etc.. );

    if ( typeFilter != null )
    {
        // filter by type
        result = result.Where( evt => evt.new_EventType.Value == (int) typeFilter.Value );
    }

    if( startDateFilter != null)
    {
        // filter by startDate
        result = result.Where(evt => evt.new_StartDate > startDateFilter.Value);
    }

    if( endDateFilter != null)
    {
        // filter by endDate
        result = result.Where(evt => evt.new_StartDate < endDateFilter.Value);
    }

    return result.Select( evt => new EventInfo()
        {
            ID = evt.Id,
            EventType = (EventType) evt.new_EventType.Value,
            ...
        }  );       
}



回答3:


If you want to use the Linq syntax, it is possible to construct a query dynamically using LinqKit.

I have used it for this purpose on the Dynamics CRM project which I'm currently working on, and it does the job very well.

Please refer to the following answer, which is where I got the idea: https://stackoverflow.com/a/5152946/344988



来源:https://stackoverflow.com/questions/15545718/nullable-filters-in-xrm-where-clause

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!