(You can attach a screenshot using the paperclip icon on the right?)
A predicate is sometimes a nested structure, expressions which have expressions as arguments. To obtain elements from a predicate you can traverse it. Below I'll give you the sourcecode of the PredicateFinder which is an internal type of the framework but which illustrates what you can do
internal class PredicateFinder : QueryApiObjectTraverser
{
#region Class Member Declarations
private List<IPredicate> _foundPredicates;
private PredicateType _predicateTypeToFind;
#endregion
/// <summary>
/// Initializes a new instance of the <see cref="PredicateFinder"/> class.
/// </summary>
/// <param name="traverseSetPredicateInnerSetElements">the flag to traverse the inner elements of a FieldCompareSetPredicate. (default is false).
/// Keep this value to false if you use the findings of this crawler to adjust an outer query, as the inner elements of a fieldcompareset are a
/// different scope.</param>
/// <remarks>this ctor finds all predicates, regardless of type.</remarks>
internal PredicateFinder(bool traverseSetPredicateInnerSetElements = false) : this(PredicateType.Undefined, traverseSetPredicateInnerSetElements)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="PredicateFinder"/> class.
/// </summary>
/// <param name="predicateTypeToFind">The predicate type to find.</param>
/// <param name="traverseSetPredicateInnerSetElements">the flag to traverse the inner elements of a FieldCompareSetPredicate. (default is false).
/// Keep this value to false if you use the findings of this crawler to adjust an outer query, as the inner elements of a fieldcompareset are a
/// different scope.</param>
internal PredicateFinder(PredicateType predicateTypeToFind, bool traverseSetPredicateInnerSetElements = false)
: base()
{
this.TraverseSetPredicateInnerSetElements = traverseSetPredicateInnerSetElements;
_foundPredicates = new List<IPredicate>();
_predicateTypeToFind = predicateTypeToFind;
}
/// <summary>
/// Traverses the specified predicate and enclosed objects.
/// </summary>
/// <param name="objectToTraverse">The object to traverse.</param>
public override void Traverse(IPredicate objectToTraverse)
{
if(objectToTraverse == null)
{
return;
}
if((_predicateTypeToFind==PredicateType.Undefined && objectToTraverse.InstanceType != (int)PredicateType.PredicateExpression) ||
objectToTraverse.InstanceType == (int)_predicateTypeToFind)
{
_foundPredicates.Add(objectToTraverse);
}
base.Traverse(objectToTraverse);
}
#region Class Property Declarations
/// <summary>
/// Gets the found predicates.
/// </summary>
internal List<IPredicate> FoundPredicates
{
get { return _foundPredicates; }
}
#endregion
}
Use it by calling Traverse() and passing in your IPredicate object.
obviously you want to do different things, like pull out information from the predicates for logging. So the IPredicate objects you run into have an instance type. You can use that to cast the IPredicate to a dedicated class like FieldCompareValuePredicate and use the values on that for your log string.
An alternative could be to generate the IPredicate to XML, by calling IPredicate.WriteXml(xmlwriter).
Another alternative would be to set its DatabaseSpecificCreator property to an instance of SqlServerSpecificCreator and call ToQueryText(). It might be this property is already set btw, if it's used in a query that was generated, so in that case you can just call ToQueryText() and you get the full SQL fragment for the predicate (with parameters, so you have to write these out manually).