【问题标题】:Entity Framework Core: Global query filter not filtering correctly after data changeEntity Framework Core:全局查询过滤器在数据更改后无法正确过滤
【发布时间】:2018-09-29 05:58:42
【问题描述】:

我们使用 Entity Framework Core 实现了软删除模式,与 this solution 非常相似,但使用可空列“DeleteDate”而不是 IsDeleted 标志。如果填写了日期,则认为该行已删除并被过滤掉:

modelBuilder.Entity<TEntity>().HasQueryFilter(e => !EF.Property<DateTime?>(e, "SysDeletedOn").HasValue);

以下代码位将在这样做时更新一项,删除其子元素之一,但在返回的项中,仍将包含已删除的子元素。只有对所有项目的新查询才能正确过滤子集合。

public async Task<Item> UpdateItemAsync(ItemDto itemDto)
{
    var itemEntity = await _context.Items.SingleOrDefaultAsync(i => i.Id == itemDto.Id);

    if(itemEntity != null)
    {
        return;
    }

    // Update item's properties here
    // ...

    foreach (var child in itemDto.Children)
    {
        // Update child here
        // ...
    }

    foreach (var child in itemDto.RemovedChildren)
    {
        var childEntity = await itemEntity.SingleOrDefaultAsync(i => i.Id == child.Id);
        _context.Remove(childEntity);
    }

    await _context.SaveChangesAsync();

    // Read and return updated item
    return await _context.Items.SingleOrDefaultAsync(i => i.Id == itemDto.Id);
}

现在的问题是:在进行此更改(删除)后,如何在此方法中获取正确的列表?我是否必须在 SaveChangesAsync 和再次读取上下文之间以某种方式清除缓存?

正确返回项目的定期更新(属性值)。此外,当我使用 .AsNoTracking() 查询项目时,它显然也关闭了缓存。

【问题讨论】:

  • 那你的问题是什么?
  • 谢谢@viveknuna,我用一个具体的问题更新了它。
  • 你能用 SaveChanges 代替 SaveChangesAsync
  • 感谢@viveknuna 的建议。我尝试了 SaveChanges,但结果是一样的。

标签: entity-framework-core


【解决方案1】:

根据链接的解决方案,您还需要分离(即停止跟踪)任何成功保存到数据库中且带有非空 SysDeletedOn 值的实体。

public override ...int SaveChanges...
{
    OnBeforeSaving();
    var result = base.SaveChanges(...);
    OnAfterSaving();

    return result;
}

private void OnAfterSaving()
{
    // you want entries for objects that have the soft delete column
    //   and whose current value for said property is not null
    // this is one way to do it if the property name is always the same
    //   but it isn't necessarily the most efficient
    //   (e.g. if there is a base type or interface for the soft delete
    //    property you can check that)
    var entries = this.ChangeTracker.Entries()
        .Where( ee => ee.Properties.Any( prop =>
            prop.Metadata.Name == "SysDeletedOn"
            && prop.CurrentValue != null ) );

    foreach( var entry in entries )
    {
        // tracked entity is soft deleted and we want to remove it from the context
        entry.State = EntityState.Detached;
    }
}

【讨论】:

    猜你喜欢
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-18
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多