-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Closed as not planned
Labels
Description
When we use ModelBuilder.HasDbFunction to add a database function to model
It generate the SQL with QUOTE char all of the arguments
With SQL Server 2016, there is a JSON_VALUE function
It's require first argument to be column without QUOTE, and second argument not be a parameter.
I wrote a test to solve first question but a bug exist.
Write a static method
public static class JsonExtensions
{
public static string JsonValue(string column, string path)
{
throw new NotSupportedException();
}
}
Write a expression translate method
public static class JsonExpressionTranslator
{
public static Expression Translate(IReadOnlyCollection<Expression> expressions)
{
var items = expressions.ToArray();
return new JsonExpression(items[0], items[1]);
}
}
Write a json expression
public class JsonExpression : Expression
{
public JsonExpression(Expression column, Expression path)
{
Column = column;
Path = path;
}
public override ExpressionType NodeType => ExpressionType.Extension;
public Expression Column { get; private set; }
public Expression Path { get; private set; }
protected override Expression Accept(ExpressionVisitor visitor)
{
if (visitor is ISqlExpressionVisitor specificVisitor)
{
string sql = $"JSON_VALUE([{Column.ToString().Trim('"')}],";
specificVisitor.VisitSqlFragment(new SqlFragmentExpression(sql));
visitor.Visit(Path);
sql = ")";
return specificVisitor.VisitSqlFragment(new SqlFragmentExpression(sql));
}
else
return base.Accept(visitor);
}
protected override Expression VisitChildren(ExpressionVisitor visitor)
{
return new JsonExpression(visitor.Visit(Column), visitor.Visit(Path));
}
public override Type Type => typeof(string);
public override string ToString() => $"JSON_VALUE([{Column.ToString().Trim('"')}], '{Path.ToString().Trim('"')}')";
}
Configure model
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDbFunction(typeof(JsonExtensions).GetMethod("JsonValue"), options => options.HasTranslation(JsonExpressionTranslator.Translate));
}
Write query
var path = "$.Filter"; //this argument used to be dynamic
var result = dbContext.Items.Where(t => JsonExtensions.JsonValue("Values", path).ToArray();
It came out sql with
JSON_VALUE([Values],@__path_1)
And column name has no table relate, path is a parameter
-- How to generate sql without QUOTE?
-- How to generate sql that argument is not a PARAMETER?