Hi, I'm trying to build an Expression to get a generic entity by its primary key and getting a parameterized sql query.
Currently I can get the correct WHERE query, but it isn't parameterized.
public async Task<TDbo> Get(TKey key, Expression<Func<TEntity, TKey>> keySelector)
{
var propertyRef = keySelector.Body;
var parameter = keySelector.Parameters[0];
var constantRef = Expression.Constant(key);
var equals = Expression.Equal(propertyRef, constantRef);
var comparer = Expression.Lambda<Func<TEntity, bool>>(equals, parameter);
return await _context.Set<TDbo>().SingleOrDefaultAsync(comparer);
}
This results in the following query:
SELECT e.\"Id\", e.\"Name\" \r\n FROM \"People\" AS e\r\nWHERE e.\"Id\" = 1\r\nLIMIT 2
,
instead of the wanted:
SELECT e.\"Id\", e.\"Name\" \r\n FROM \"People\" AS e\r\nWHERE e.\"Id\" = @__s_0\r\nLIMIT 2
答案 0 :(得分:4)
这是因为Session_End
。值常量表达式未由查询转换器参数化。您需要的是一个引用另一个表达式的属性或字段的表达式(可以为常数)。基本上,这就是C#编译器发出的用于关闭的内容。
一种方法是实际使用C#编译器创建带闭包的lambda表达式并获取主体:
Expression.Constant(key)
({Expression<Func<TKey>> keyValue = () => key;
var variableRef = key.Body;
代替了您的variableRef
)
另一种方法是使用匿名,元组或特定的类类型创建显式的闭包实例并绑定相应的属性或字段。例如,使用匿名类型:
constantRef
或使用var variableRef = Expression.Property(Expression.Constant(new { key }), "key");
:
System.Tuple
实际方法并不重要(我个人更喜欢使用lambda的第一个变体)-所有这些都会导致EF Core查询翻译器创建参数。