C# .net通用方法,带参数iquiryable<;T>;和表达<;Func<;T、 T>&燃气轮机;

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

我想为这个函数创建一个泛型方法,并发送用户类和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;
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}
我已经更新了我的答案。如果你能得到你想要更新的属性,你可以自己构建表达式。