C# .net通用方法,带参数iquiryable<;T>;和表达<;Func<;T、 T>&燃气轮机;
我想为这个函数创建一个泛型方法,并发送用户类和where子句之类的参数C# .net通用方法,带参数iquiryable<;T>;和表达<;Func<;T、 T>&燃气轮机;,c#,entity-framework,expression,iqueryable,C#,Entity Framework,Expression,Iqueryable,我想为这个函数创建一个泛型方法,并发送用户类和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
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;
publicstaticintupdate(这个IQueryable查询,expressionupdatefactory),其中T:class;
如果您传递一个已创建的用户
实例,则更新
方法将无法知道要更新哪些属性(例如,它应该更新所有属性吗?还是更新具有非默认值的属性?如果故意将属性设置为默认值怎么办?)
您需要传递包含成员初始化表达式的表达式,例如x=>newuser(){Name=“Jack”}
表达式是作为数据的代码。在内部,框架将解析表达式并查看要更新的属性。在本例中,它将看到只有Name
属性打算更新
至于where表达式,您需要传递expression
。因此,您的方法如下所示:
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);
}
编辑:
如果您有办法找到要更新的属性,可以按如下方式构建表达式:
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);
}
公共静态无效更新(
表达条件,
用户,
PropertyInfo[]propertiesToUpdate)
{
表达式更新因子=
Lambda(
Expression.MemberInit(
Expression.New(typeof(User)),
属性更新
.选择(prop=>
表达式绑定(
prop.SetMethod,
Expression.Constant(prop.GetValue(用户')),
表达式.参数(类型(用户),“u”);
用户
.何处(条件)
.Update(updateFactory);
}
如果只有属性名,则可以使用该方法获取相应的PropertyInfo
是否需要传递已创建的用户实例?或者可以传递更新工厂,如x=>newuser(){Name=“Jack”}
?是。我传递了一个以前创建的用户实例。User
类是否具有Name
以外的其他属性?如果是,那么更新
方法是否也应该更新其他属性?例如,假设有一个Age
属性,它是否也应该更新?Update
方法如何知道要更新哪些属性?是的,用户类有更多属性。我在将对象发送到函数之前设置了属性。是。但它应该更新哪些属性?都是吗?请注意,一旦创建了对象,就无法分辨您设置了哪些对象,哪些对象未设置。例如,如果您的int Age
属性的值为0
,这可能意味着它在初始化期间未设置,或者显式设置为0
。也许将Age
设置为0
才是您真正希望更新所做的。如果我只想传递对象用户并使用函数生成表达式,我该怎么做?我想检查属性是否是这样设置的:var entry=\u Context.entry(entity);foreach(entry.OriginalValues.PropertyNames中的var属性){var original=entry.OriginalValues.GetValue(属性);var current=entry.CurrentValues.GetValue(属性);if(original!=null&&!original.Equals(当前)){---property change attach to expression}
我已经更新了我的答案。如果你能得到你想要更新的属性,你可以自己构建表达式。