【问题标题】:linq expression for ExecuteUpdateAsyncExecuteUpdateAsync 的 linq 表达式
【发布时间】:2022-12-22 23:09:50
【问题描述】:

我以极大的热情在 EF Core 7 中找到了 ExecuteDeleteAsync 和 ExecuteUpdateAsync。它们有助于使我的代码更加简单和快速。批量删除或更新1-2个字段无需使用自制程序。 无论如何,在运行时应该选择要更新的确切表和数据库字段的情况。

我可以使用数据库表:

public static IQueryable<object> Set(this DbContext context, Type entity) =>
        context.ClrQuery(context.ClrType(entity));

我有使表达式过滤行的方法:

public static IQueryable Where(this IQueryable source, string equalProperty, object value, [NotNull] Type EntityType)
{
    PropertyInfo? property = EntityType.GetProperty(equalProperty);
    if (property == null)
        throw new NotImplementedException($"Type {EntityType.Name} does not contain property {equalProperty}");

    ParameterExpression parameter = Expression.Parameter(EntityType, "r");
    MemberExpression member = Expression.MakeMemberAccess(parameter, property);
    LambdaExpression whereExpression = Expression.Lambda(Expression.Equal(member, Expression.Constant(value, property.PropertyType)), parameter);
    MethodCallExpression resultExpression = WhereCall(source, whereExpression);
    return source.Provider.CreateQuery(resultExpression);
}

所以我可以找到要使用的行进行更新

IQueryable Source = db.Set(EntityType).Where(FieldName, FieldValue, EntityType);
            

我应该表达更新IQueryable ExecuteUpdateQuery = Source.ExecuteUpdateAsync(EntityType, FieldName, FieldValue);

SetProperty 表达式的访问方式是什么?

【问题讨论】:

  • ExecuteUpdateAsync 的返回值应该是 Task<int>,而不是 IQueryable

标签: linq entity-framework-core expression-trees c#-11.0 ef-core-7.0


【解决方案1】:

尝试以下扩展。我还更正了方法签名:

var affected = anyQuery.ExecuteUpdate(FieldName, FieldValue);

var affected = await anyQuery.ExecuteUpdateAsync(FieldName, FieldValue, cancellationToken);

和实施:

public static class DynamicRelationalExtensions
{
    static MethodInfo UpdateMethodInfo =
        typeof(RelationalQueryableExtensions).GetMethod(nameof(RelationalQueryableExtensions.ExecuteUpdate));

    static MethodInfo UpdateAsyncMethodInfo =
        typeof(RelationalQueryableExtensions).GetMethod(nameof(RelationalQueryableExtensions.ExecuteUpdateAsync));

    public static int ExecuteUpdate(this IQueryable query, string fieldName, object? fieldValue)
    {
        var updateBody = BuildUpdateBody(query.ElementType, fieldName, fieldValue);

        return (int)UpdateMethodInfo.MakeGenericMethod(query.ElementType).Invoke(null, new object?[] { query, updateBody });
    }

    public static Task<int> ExecuteUpdateAsync(this IQueryable query, string fieldName, object? fieldValue, CancellationToken cancellationToken = default)
    {
        var updateBody = BuildUpdateBody(query.ElementType, fieldName, fieldValue);

        return (Task<int>)UpdateAsyncMethodInfo.MakeGenericMethod(query.ElementType).Invoke(null, new object?[] { query, updateBody, cancellationToken })!;
    }

    static LambdaExpression BuildUpdateBody(Type entityType, string fieldName, object? fieldValue)
    {
        var setParam = Expression.Parameter(typeof(SetPropertyCalls<>).MakeGenericType(entityType), "s");
        var objParam = Expression.Parameter(entityType, "e");

        var propExpression = Expression.PropertyOrField(objParam, fieldName);
        var valueExpression = ValueForType(propExpression.Type, fieldValue);

        // s.SetProperty(e => e.SomeField, value)
        var setBody = Expression.Call(setParam, nameof(SetPropertyCalls<object>.SetProperty),
            new[] { propExpression.Type }, Expression.Lambda(propExpression, objParam), valueExpression);

        // s => s.SetProperty(e => e.SomeField, value)
        var updateBody = Expression.Lambda(setBody, setParam);

        return updateBody;
    }

    static Expression ValueForType(Type desiredType, object? value)
    {
        if (value == null)
        {
            return Expression.Default(desiredType);
        }

        if (value.GetType() != desiredType)
        {
            value = Convert.ChangeType(value, desiredType);
        }

        return Expression.Constant(value);
    }
}

【讨论】:

    【解决方案2】:

    谢谢,它工作得很好。

    【讨论】:

      【解决方案3】:

      @Svyatoslav Danyliv

      请帮我怎么写

      int ExecuteUpdate(此 IQueryable 查询,Dictionary<string, object?> 字段)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-08-11
        • 2018-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多