带有参数 IQueryable<T> 和 Expression<Func<T, T>> 的 .net 通用方法
.net generic method with params IQueryable<T> and Expression<Func<T, T>>
我想为此函数创建一个通用方法并向用户发送 class 和 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;
如果你传递一个已经创建的 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
.
我想为此函数创建一个通用方法并向用户发送 class 和 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;
如果你传递一个已经创建的 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
.