Following this post marked answer, I've copied Evaluator.cs into my project for partial evaluations to be able to resolve local variables of the expression. Regardless, it seems I'm missing something because for me it does not simplify the expression and the constants are kept as the original expression as an instance of an anonymous class generated by the compiler:
My VisitMember method of my visitor looks like this:
protected override Expression VisitMember(MemberExpression m)
{
if (m.Expression != null && m.Expression.NodeType == ExpressionType.Parameter)
{
sqlBuilder.AddColumn(m.Member.GetFieldName());
return m;
}
else if (m.Expression != null && m.Expression.NodeType == ExpressionType.Constant)
{
var partialEval = Evaluator.PartialEval(m.Expression);
this.Visit(partialEval);
return m;
}
throw new NotSupportedException(string.Format("The member '{0}' is not supported", m.Member.Name));
}
UPDATE: For better understanding of whay I'm trying to do, here's a unit test I'm performing in order to test that the output sql is correct:
[Theory]
[InlineData("Test1")]
[InlineData("Test2")]
[InlineData("Test3")]
public void SelectWhereExpression_NameEquals(string name)
{
using var sqlbuilder = GetSpecificBuilder();
string sql = sqlbuilder.Select()
.Where(obj => obj.Name == name)
.Build().SqlCommand;
var selectSql = SelectAllRecordsExpectedSql.Remove(SelectAllRecordsExpectedSql.Length - 1, 1);
Assert.Equal($"{selectSql} WHERE (Name = '{name}')", sql);
}
The .Where() method takes as parameter the expression and it calls my SqlVisitor with that expression:
public virtual SqlBuilder<T> Where(Expression<Func<T, bool>> expression)
{
BuiltObject.Append(" WHERE");
ExpressionToSQLVisitor<T> expressionToSQL = new(this);
expressionToSQL.Visit(expression);
return this;
}
What am I doing wrong?
Will change a little bit your code. How do you plan to render values is up to you. Main change is overriding
VisitConstantinExpressionToSQLVisitor.