Пакетное обновление указать столбец динамически

Я собираюсь использовать библиотеку http://github.com/loresoft/EntityFramework.Extended для пакетного обновления. Вот пример кода, который нужно использовать для пакетного обновления:

context
.Tasks
.Where(t => t.StatusId == 1)
.Update(t => new Task { StatusId = 2 }) 

Я хочу указать StatusId или другие свойства, такие как Discontinued, UnitsInStock, который указывается пользователем.

Как я могу достичь этого, передав свойство в виде строки и построить динамическое выражение.

1 ответ

Пока обновления относятся к статическим значениям (т. Е. Не ссылаются на другие переменные), вы можете использовать следующий метод:

public static Expression<Func<T,T>> CreateNewObjectExpression<T>(Dictionary<string, object> props) {
    // set props
    var type = typeof(T);
    // This is the `new T` part of the expression
    var newExpr = Expression.New(type);
    // Convert the values to set to expressions
    var members = from prop in props
                  let val = Expression.Constant(prop.Value)
                  select new KeyValuePair<string, Expression>(prop.Key, val);
    // this is the full new T { prop1 = val1 ... }
    var initExpr = BindMembers(newExpr, members);

    // And now we add the parameter part `t => `
    return Expression.Lambda<Func<T, T>>(initExpr, Expression.Parameter(typeof(T)));
}

static MemberInitExpression BindMembers(NewExpression expr, IEnumerable<KeyValuePair<string, Expression>> assignments) {
    Type type = expr.Type;
    List<MemberBinding> bindings = new List<MemberBinding>();
    foreach (var pair in assignments) {
        MethodInfo info = type.GetProperty(pair.Key).GetSetMethod();
        MemberBinding binding = Expression.Bind(info, pair.Value);
        bindings.Add(binding);
    }
    return Expression.MemberInit(expr, bindings);
}

Эти методы можно использовать так:

var props = new Dictionary<string,object>();
// get the properties from the user instead, of course
props["StatusId"] = 2;
// Now get the expression:
var updateExpr = CreateNewObjectExpression<Task>(props);
// and apply it
context.Tasks.Where(t => t.StatusId == 1)
    .Update(updateExpr);

Будьте внимательны, устанавливая только те свойства, которые присутствуют и доступны для записи в целевом классе, иначе вы получите сбой.

Другие вопросы по тегам