mix*_*tch 4 c# asp.net entity-framework-core
嗨,我正在尝试构建一个表达式,以通过其主键获取通用实体,并获取参数化的sql查询。
当前,我可以获取正确的WHERE查询,但未对其进行参数化。
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);
}
Run Code Online (Sandbox Code Playgroud)
这将导致以下查询:
SELECT e.\"Id\", e.\"Name\" \r\n FROM \"People\" AS e\r\nWHERE e.\"Id\" = 1\r\nLIMIT 2,而不是通缉:
SELECT e.\"Id\", e.\"Name\" \r\n FROM \"People\" AS e\r\nWHERE e.\"Id\" = @__s_0\r\nLIMIT 2
是因为Expression.Constant(key)。值常量表达式未由查询转换器参数化。您需要一个引用另一个表达式的属性或字段的表达式(可以是常量)。基本上,这就是C#编译器发出的用于闭包的内容。
一种方法是实际使用C#编译器创建带闭包的lambda表达式并获取主体:
Expression<Func<TKey>> keyValue = () => key;
var variableRef = key.Body;
Run Code Online (Sandbox Code Playgroud)
(这variableRef是您的替代品constantRef)
另一种方法是使用匿名,元组或特定的类类型创建显式的闭包实例并绑定相应的属性或字段。例如,使用匿名类型:
var variableRef = Expression.Property(Expression.Constant(new { key }), "key");
Run Code Online (Sandbox Code Playgroud)
或搭配System.Tuple:
var variableRef = Expression.Property(Expression.Constant(Tuple.Create(key)), "Item1");
Run Code Online (Sandbox Code Playgroud)
实际的方法并不重要(我个人更喜欢使用lambda的第一个变体)-所有这些都会导致EF Core查询转换器创建参数。
| 归档时间: |
|
| 查看次数: |
145 次 |
| 最近记录: |