Search code examples
c#linqepiserver

Incorrect sql syntax in EpiServer DynamicDataStore LINQ statement


I'm writing a query to retrieve some data from a DynamicDataStore in Episerver. When I run the code I get the following error:

System.Data.SqlClient.SqlException: Incorrect syntax near '>'.

Here's the relevant query:

BlogContentStore store = new BlogContentStore();
IQueryable<UwlBlogPost> posts = store.Posts.Where(p => Blog == p.BlogId && p.ReadyToPost && p.PostOn <= DateTime.Now);
if (taggedPeople.Count() > 0 || taggedDepartments.Count() > 0 || taggedDepartments.Count() > 0)
{
    posts = posts.Where(p => p.PeopleTags.Intersect(taggedPeople).Count() > 0
        || p.DepartmentTags.Intersect(taggedDepartments).Count() > 0
        || p.KeywordTags.Intersect(taggedKeywords).Count() > 0);
}
posts = posts.OrderByDescending(p => p.PostOn).Take(DisplayCount);

The syntax for everything looks alright to me, and it compiles okay.


Solution

  • I managed to solve the issue. Looking at the SQL server log I was able to see that the Intersect statements were not getting turned into SQL, so I decided to dynamicly create the query expression to get around it:

    if (taggedPeople.Count > 0 || taggedDepartments.Count > 0 || taggedKeywords.Count > 0)
    {
        ParameterExpression paramExpr = Expression.Parameter(typeof(UwlBlogPost), "p");
        Expression peopleTagsExpr = Expression.Property(paramExpr, "PeopleTags");
        Expression deptTagsExpr = Expression.Property(paramExpr, "DepartmentTags");
        Expression keywordTagsExpr = Expression.Property(paramExpr, "KeywordTags");
    
        Expression filterExpr = null;
        if(taggedPeople.Count > 0)
        {
            filterExpr = FilterLambda<string>(taggedPeople, peopleTagsExpr, paramExpr);
        }
        if(taggedDepartments.Count > 0)
        {
            Expression filter = FilterLambda<int>(taggedDepartments, deptTagsExpr, paramExpr);
            filterExpr = (filterExpr == null) ? filter : MatchAll ? Expression.And(filterExpr, filter) : Expression.Or(filterExpr, filter);
        }
        if(taggedKeywords.Count > 0)
        {
            Expression filter = FilterLambda<int>(taggedKeywords, keywordTagsExpr, paramExpr);
            filterExpr = (filterExpr == null) ? filter : MatchAll ? Expression.And(filterExpr, filter) : Expression.Or(filterExpr, filter);
        }
    
        posts = posts.Where(Expression.Lambda<Func<UwlBlogPost, bool>>(filterExpr, new[] { paramExpr }));
    }
    
    
    private Expression FilterLambda<T>(List<T> tags, Expression field, ParameterExpression paramExpr)
    {
        Expression firstTag = Expression.Constant(tags.First());
        Expression root = Expression.Call(field, tags.GetType().GetMethod("Contains"), firstTag);
        if (tags.Count > 1)
        {
            foreach (T tag in tags.Skip(1))
            {
                Expression singleTag = Expression.Constant(tag);
                Expression cond = Expression.Call(field, tags.GetType().GetMethod("Contains"), singleTag);
                root = MatchAll ?  Expression.And(root, cond) : Expression.Or(root, cond);
            }
        }
        return root;
    }