如何通过反射结合EF Core的ExecuteUpdate()更新数据库?代码报错求助
问题描述
尝试通过反射结合Entity Framework Core的ExecuteUpdate()方法更新数据库,编写的代码如下:
public async Task<bool> UpdateUserProperty(string username, string property, object value) { // Using Reflection: _TMSContext.Users .Where(u => u.UserName == username) .ExecuteUpdate(s => s.SetProperty(u => u.GetType().GetProperty(property), value)); // Trying to use reflection to accomplish this: //_TMSContext.Users // .Where(u => u.UserName == username) // .ExecuteUpdate(s => s.SetProperty(u => u.ForceChangePasswordInd, value)); return true; }
运行代码时抛出错误:
System.InvalidOperationException: 'The LINQ expression 'DbSet()
.Where(u => u.UserName == __username_0)
.ExecuteUpdate(s => s.SetProperty(
propertyExpression: u => u.GetType().GetProperty(__property_1),
valueExpression: __value_2))' could not be translated. Additional information: The following lambda argument to 'SetProperty' does not represent a valid property to be set: 'u => u.GetType().GetProperty(__property_1)'
解决方案
EF Core无法将反射调用(如u.GetType().GetProperty(property))翻译为SQL,因为ExecuteUpdate需要明确的属性访问表达式来生成更新语句。需手动构建属性访问的表达式树来实现动态更新:
实现代码
using System.Linq.Expressions; public async Task<bool> UpdateUserProperty(string username, string property, object value) { // 验证目标属性是否存在 var propertyInfo = typeof(User).GetProperty(property); if (propertyInfo == null) { return false; } // 构建参数表达式:u => u var userParam = Expression.Parameter(typeof(User), "u"); // 构建属性访问表达式:u => u.[指定属性] var propertyAccess = Expression.Property(userParam, propertyInfo); var propertyLambda = Expression.Lambda(propertyAccess, userParam); // 构建SetProperty的调用表达式 var setPropertyMethod = typeof(SetPropertyCalls<User>) .GetMethod(nameof(SetPropertyCalls<User>.SetProperty)) .MakeGenericMethod(propertyInfo.PropertyType); var updateLambda = Expression.Lambda( Expression.Call( Expression.Parameter(typeof(SetPropertyCalls<User>), "s"), setPropertyMethod, propertyLambda, Expression.Constant(value, propertyInfo.PropertyType) ), Expression.Parameter(typeof(SetPropertyCalls<User>), "s") ); // 执行更新并获取受影响行数 var affectedRows = await _TMSContext.Users .Where(u => u.UserName == username) .ExecuteUpdateAsync(updateLambda); return affectedRows > 0; }
关键说明
ExecuteUpdate仅接受直接的属性访问Lambda,反射调用无法被EF Core解析为SQL,必须通过表达式树生成符合要求的表达式。- 添加属性存在性校验可避免因传入无效属性名导致的异常。
- 最终通过构建的表达式树,EF Core能正确生成对应的UPDATE SQL语句,实现动态更新指定属性。
内容的提问来源于stack exchange,提问作者Christopher G
相关产品推荐
相关产品推荐

