我想为此函数创建一个泛型方法,并发送用户类和where子句,如参数。
public void Update(where clause, User user) {}
但我找不到正确的方法。
ctx.Users.Where(x => x.Id == 10)
.Update(x => new User() { Name = "Jack" });
方法声明是:
public static int Update<T>(this IQueryable<T> query, Expression<Func<T, T>> updateFactory) where T : class;
答案 0 :(得分:0)
如果您传递已创建的User
实例,Update
方法将无法知道要更新哪些属性(例如,是否应更新所有属性?或者具有非默认值的属性) ?如果故意将财产设置为默认值怎么办?)。
您需要传递包含成员初始化表达式的Expression<Func<T, T>>
表达式,例如x => new User() { Name = "Jack" }
。
表达式是代码作为数据。在框架内部,框架将解析表达式并查看要更新的属性。在示例的情况下,它将看到仅更新Name
属性。
至于where表达式,您需要传递Expression<Func<User,bool>>
。所以你的方法看起来像这样:
public void Update(
Expression<Func<User,bool>> condition,
Expression<Func<User,User>> updateFactory)
{
ctx.Users
.Where(condition)
.Update(updateFactory);
}
你可以像这样使用它:
Update(x => x.Id == 10, x => new User() { Name = "Jack" });
修改强>
如果您有办法找到要更新的属性,可以构建如下表达式:
public static void Update(
Expression<Func<User, bool>> condition,
User user,
PropertyInfo[] propertiesToUpdate)
{
Expression<Func<User, User>> updateFactory =
Expression.Lambda<Func<User, User>>(
Expression.MemberInit(
Expression.New(typeof (User)),
propertiesToUpdate
.Select(prop =>
Expression.Bind(
prop.SetMethod,
Expression.Constant(prop.GetValue(user))))),
Expression.Parameter(typeof(User), "u"));
ctx.Users
.Where(condition)
.Update(updateFactory);
}
如果您只有属性名称,则可以使用Type.GetProperty方法获取相应的PropertyInfo
。