var query = QueryFactory.Queryable<Contact>(mockBucket.Object) .WhereMissing(e => e.Age) .OrderBy(e => e.Age) .Select(e => new { age = e.Age, name = e.FirstName });
Where I am stuck is on how to register this new node type with Relinq. There seems to be almost no documentation concerning this.
I found this tutorial: https://www.re-motion.org/blogs/mix/2010/10/28/re-linq-extensibility-custom-query-operators/
But what I'm trying to implement doesn't seem to be a result operator. This isn't acting on the result of the query like Count or Take. This new operator would get translated into some N1QL that looked like "WHERE e.Age IS MISSING" This essentially means the property of this NoSQL document isn't present (i.e. not the same meaning as IS NULL).
I'm guessing I have to implement "ExtensionExpression" as a base class, but after that I'm unsure of the next step.
Anyone have any experience with this?
Sam
var query = QueryFactory.Queryable<Contact
>(mockBucket.Object)
.Where(e => e.Age.IsMissing())
.OrderBy(e => e.Age)
.Select(e => new { age = e.Age, name = e.FirstName });
--
You received this message because you are subscribed to the Google Groups "re-motion Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to re-motion-use...@googlegroups.com.
To post to this group, send email to re-moti...@googlegroups.com.
Visit this group at http://groups.google.com/group/re-motion-users.
For more options, visit https://groups.google.com/d/optout.
public static IQueryParser CreateQueryParser()
{
var customNodeTypeRegistry = new MethodInfoBasedNodeTypeRegistry();
customNodeTypeRegistry.Register(WhereMissingExpressionNode.SupportedMethods, typeof(WhereMissingExpressionNode));
var nodeTypeProvider = ExpressionTreeParser.CreateDefaultNodeTypeProvider();
nodeTypeProvider.InnerProviders.Add(customNodeTypeRegistry);
var transformerRegistry = ExpressionTransformerRegistry.CreateDefault();
var processor = ExpressionTreeParser.CreateDefaultProcessor(transformerRegistry);
var expressionTreeParser = new ExpressionTreeParser(nodeTypeProvider, processor);
var queryParser = new QueryParser(expressionTreeParser);
return queryParser;
}
public class WhereMissingClause : IBodyClause
{
private Expression _predicate;
/// <summary>
/// Initializes a new instance of the <see cref="WhereMissingClause"/> class.
/// </summary>
/// <param name="predicate">The predicate used to filter data items.</param>
public WhereMissingClause (Expression predicate)
{
_predicate = predicate;
}
/// <summary>
/// Gets the predicate, the expression representing the where condition by which the data items are filtered
/// </summary>
public Expression Predicate
{
get { return _predicate; }
set { _predicate = value; }
}
/// <summary>
/// Accepts the specified visitor
/// </summary>
/// <param name="visitor">The visitor to accept.</param>
/// <param name="queryModel">The query model in whose context this clause is visited.</param>
/// <param name="index">The index of this clause in the <paramref name="queryModel"/>'s <see cref="QueryModel.BodyClauses"/> collection.</param>
public virtual void Accept (IQueryModelVisitor visitor, QueryModel queryModel, int index)
{
var visotorx = visitor as N1QlQueryModelVisitor;
if (visotorx != null) visotorx.VisitWhereMissingClause(this, queryModel, index);
}
/// <summary>
/// Transforms all the expressions in this clause and its child objects via the given <paramref name="transformation"/> delegate.
/// </summary>
/// <param name="transformation">The transformation object. This delegate is called for each <see cref="Expression"/> within this
/// clause, and those expressions will be replaced with what the delegate returns.</param>
public void TransformExpressions (Func<Expression, Expression> transformation)
{
Predicate = transformation (Predicate);
}
/// <summary>
/// Clones this clause.
/// </summary>
/// <param name="cloneContext">The clones of all query source clauses are registered with this <see cref="CloneContext"/>.</param>
/// <returns></returns>
public virtual WhereMissingClause Clone (CloneContext cloneContext)
{
var clone = new WhereMissingClause (Predicate);
return clone;
}
IBodyClause IBodyClause.Clone (CloneContext cloneContext)
{
return Clone (cloneContext);
}
public override string ToString ()
{
return "WHERE MISSING " + FormattingExpressionTreeVisitor.Format (Predicate);
}
}
public class WhereMissingExpressionNode : MethodCallExpressionNodeBase
{
public static readonly MethodInfo[] SupportedMethods = new[]
{
GetSupportedMethod (() => QueryExtensions.WhereMissing<object, object> (null, o => null)),
GetSupportedMethod (() => QueryExtensions.WhereMissing<object, int> (null, o => 10))
};
private readonly ResolvedExpressionCache<Expression> _cachedPredicate;
public WhereMissingExpressionNode(MethodCallExpressionParseInfo parseInfo, LambdaExpression predicate)
: base(parseInfo)
{
if (predicate.Parameters.Count != 1)
throw new ArgumentException("Predicate must have exactly one parameter.", "predicate");
Predicate = predicate;
_cachedPredicate = new ResolvedExpressionCache<Expression>(this);
}
public LambdaExpression Predicate { get; private set; }
public Expression GetResolvedPredicate(ClauseGenerationContext clauseGenerationContext)
{
var expression = _cachedPredicate.GetOrCreate(r => r.GetResolvedExpression(Predicate.Body, Predicate.Parameters[0], clauseGenerationContext));
return expression;
}
public override Expression Resolve(ParameterExpression inputParameter, Expression expressionToBeResolved, ClauseGenerationContext clauseGenerationContext)
{
return Source.Resolve(inputParameter, expressionToBeResolved, clauseGenerationContext);
}
protected override QueryModel ApplyNodeSpecificSemantics(QueryModel queryModel, ClauseGenerationContext clauseGenerationContext)
{
queryModel.BodyClauses.Add(new WhereMissingClause(GetResolvedPredicate(clauseGenerationContext)));
return queryModel;
}
}
public void VisitWhereMissingClause(WhereMissingClause whereClause, QueryModel queryModel, int index)
{
var expression = GetN1QlExpression(whereClause.Predicate);
_queryPartsAggregator.AddWhereMissingPart(String.Concat(expression, " IS MISSING"));
}
var query =
QueryFactory.Queryable<Contact>(mockBucket.Object)
.Where(e => e.Email == "some...@gmail.com")
.WhereMissing(e => e.Age)
.OrderBy(e => e.Age)
.Select(e => new { age = e.Age, name = e.FirstName });