Camlex.Query().WhereAny().Where()

Jan 21, 2011 at 9:23 AM
var expressions = new List<Expression<Func<SPListItem, bool>>>(3);
if (typesFilter.Length != 4)
{
   for (int i = 0; i < typesFilter.Length; i++)
   {
      var ind = i;
      expressions.Add(x => (string)x[adsOnjList.Fields["Field"].Id] == typesFilter[ind]);
   }
}
else
   camlexQuery = Camlex.Query();

camlexQuery = Camlex.Query().WhereAny(expressions).Where(x => x[adsOnjList.Fields["Field2"].Id] == (DataTypes.LookupId)ownerId.ToString());
query.Query = camlexQuery.OrderBy(z => z[SPBuiltInFieldId.Title]).ToString();

resylt is:

<Where>
  <Eq>
    <FieldRef ID="0c48163f-febf-412b-9467-71ca09a86802" LookupId="True" />
    <Value Type="Lookup">7</Value>
  </Eq>
</Where>
<OrderBy>
  <FieldRef ID="fa564e0f-0c70-4ab9-b863-0177e6ddd247" />
</OrderBy>

WhereAny() was overloaded by Where(). Have any way to concat it?
Developer
Jan 21, 2011 at 10:59 AM

In this case, you have to use "CamlexNET.Impl.Helpers.ExpressionsHelper" public class.

This class combines many expressions into single one with AND or OR logic.

WhereAll and WhereAny methods of Query class are implemented in simple manner:

public IQuery WhereAll(IEnumerable<Expression<Func<SPListItem, bool>>> expressions)
{
    var combinedExpression = ExpressionsHelper.CombineAnd(expressions);
    return this.Where(combinedExpression);
}

public IQuery WhereAny(IEnumerable<Expression<Func<SPListItem, bool>>> expressions)
{
    var combinedExpression = ExpressionsHelper.CombineOr(expressions);
    return this.Where(combinedExpression);
}

So it can give you a clue how to use ExpressionHelper class:

  1. Initially, you combine all expressions (like you do in your example)
  2. then instead of calling WhereAny method, you call ExpressionHeper.CombineOr() method
  3. it will give you single expression from expressions combined with OR logic
  4. then create new expression with lookup field
  5. create an expression list containing 2 expressions - first calculated on step 3 and the second on step 4
  6. then call ExpressionHeper.CombineAnd() method with the expression list
  7. then call Query.Where with resulting single expression

I hope, it will help!

Coordinator
Jan 21, 2011 at 11:37 AM
Edited Jan 21, 2011 at 11:37 AM

hi

currently if several Where... methods (Where, WhereAny or WhereAll) are used in the single call chain, only the last method is actually applied. You can use workaround suggested by Vladimir.

Probably we should do something in order to avoid such misleading in the future. Vladimir, how about using the same approach we used for distinguish calls to ViewFields() method (if you remember we return another interface instance from this method so it is not possible to call other ICamlex methods after it)? In this case there will no be such problems.

Jan 21, 2011 at 11:54 AM

Thanks, it's helpfull solve!

Jan 21, 2011 at 12:07 PM
Edited Jan 21, 2011 at 12:11 PM
sadomovalex wrote:

hi

currently if several Where... methods (Where, WhereAny or WhereAll) are used in the single call chain, only the last method is actually applied. You can use workaround suggested by Vladimir.

Probably we should do something in order to avoid such misleading in the future. Vladimir, how about using the same approach we used for distinguish calls to ViewFields() method (if you remember we return another interface instance from this method so it is not possible to call other ICamlex methods after it)? In this case there will no be such problems.

I want to say some about your relalization of ViewFields() method. It isn't comfort to use. Lamba expression for build ViewField string is excess accumulation of code. It's enough to pass array of Giud or InternalNames of fields to function. Like this:

        public static string FieldRef(Guid FieldID)
        {
            return string.Format("<FieldRef ID='{0}' />", FieldID);
        }
        public static string ViewFields(string[] fieldsNames, SPList list)
        {
            string res = string.Empty;
            foreach (string fieldName in fieldsNames)
                res += FieldRef(list.Fields[fieldName].Id);
            return res;
        }
        public static string ViewFields(Guid[] fieldsNames)
        {
            string res = string.Empty;
            foreach (var fieldName in fieldsNames)
                res += FieldRef(fieldName);
            return res;
        }
Example of use:
query.ViewFields=ViewFields(new[] 
     { 
         SPBuiltInFieldId.Title,
         spList.Fields["Field1"].Id,
         spList.Fields["Field2"].Id,
         spList.Fields["Field3"].Id 
    }
    )
or
query.ViewFields=ViewFields(new[] 
     { 
         "Title",
         "Field1",
         "Field2",
         "Field3"
    },
    spList)

IMHO it's easy to use.
Coordinator
Jan 21, 2011 at 12:20 PM

thanks for your feedback. We used lambdas in order to keep things similar (like e.g. in OrderBy, GroupBy). We will think about your proposal and try to make it more convenient in next release.

Jan 21, 2011 at 12:23 PM
sadomovalex wrote:

thanks for your feedback. We used lambdas in order to keep things similar (like e.g. in OrderBy, GroupBy). We will think about your proposal and try to make it more convenient in next release.

thank you for helpful and free tool :)

Mar 12 at 10:07 AM
sadomovalex wrote:
hi currently if several Where... methods (Where, WhereAny or WhereAll) are used in the single call chain, only the last method is actually applied.
Hi, we created rule in SPCAFContrib for this case and use text from this thread in help page.
https://spcafcontrib.codeplex.com/wikipage?title=CSC510224_CamlexQueryDoubleWhere

Is it OK?
Coordinator
Mar 12 at 10:27 AM
hello dvd73,
currently there are no plans to change this behavior, so it is Ok from my point of view.