如何使用 Entity Framework Core ExecuteUpdate 有条件地 SetProperty?

Han*_*tie 6 c# entity-framework-core

使用 EF Core 查询数据库时,可以.Where在执行查询之前轻松有条件地向查询添加子句,例如:

[HttpGet]
public async Task<List<Entity>> GetEntitiesAsync(string? property1, string? property2)
{
    var query = _context.Entities.AsNoTracking();
    if (property1 != null)
    {
        query = query.Where(e => e.Property1.Contains(property1));
    }
    if (property2 != null)
    {
        query = query.Where(e => e.Property2.Contains(property2));
    }
    return await query.ToListAsync();
}
Run Code Online (Sandbox Code Playgroud)

但是,当使用 时.ExecuteUpdate,我看不到如何有条件地链接.SetProperty子句:

[HttpPatch("{id}")]
public async Task<IActionResult> UpdateEntityAsync(int id, Entity entity)
{
    var entitiesUpdated = await _context.Entities
        .Where(e => e.Id == id)
        .ExecuteUpdateAsync(s => s
            // How to conditionally chain SetProperty based on
            // if entity.Property1 and entity.Property2 are null?
            .SetProperty(e => e.Property1, entity.Property1)
            .SetProperty(e => e.Property2, entity.Property2)
    );

    return entitiesUpdated == 1 ? NoContent() : NotFound();
}
Run Code Online (Sandbox Code Playgroud)

您不能if在 lambda 内部使用语句。它必须是计算结果为 的单个表达式SetPropertyCalls<T>。也许您可以手动创建一个表达式树,但是您不需要在传递到 lambda 的参数之上构建它吗?有没有我没有看到的简单方法?

Gur*_*ron 7

SetProperty允许传递表达式来计算值。SetProperty要根据条件动态组合调用,您可以使用三元条件运算符

var entitiesUpdated = await _context.Entities
    .Where(e => e.Id == id)
    .ExecuteUpdateAsync(s => s
         .SetProperty(e => e.Property1, e => entity.Property1 != null
              ? entity.Property1
              : e.Property1)
         .SetProperty(e => e.Property2, , e => entity.Property2 != null
              ? entity.Property2
              : e.Property2));
Run Code Online (Sandbox Code Playgroud)

尽管这会生成类似于"PropertyX" = "e"."PropertyX"源为null.

执行“条件”批量更新的更困难但更“正确”的方法是执行一些表达式树操作

var entitiesUpdated = await _context.Entities
    .Where(e => e.Id == id)
    .ExecuteUpdateAsync(s => s
         .SetProperty(e => e.Property1, e => entity.Property1 != null
              ? entity.Property1
              : e.Property1)
         .SetProperty(e => e.Property2, , e => entity.Property2 != null
              ? entity.Property2
              : e.Property2));
Run Code Online (Sandbox Code Playgroud)