Entity Framework Core 验证 SaveChanges 计数

Pri*_*hal 3 entity-framework-core asp.net-core asp.net-core-3.1 ef-core-3.1 entity-framework-core-3.1

我被分配了一项任务来验证使用SaveChanges(). 开发人员应该预先知道在调用时将更改多少条记录。SaveChanges()

为了实现它,我创建了一个扩展方法,用于在我使用事务的地方DbContext调用SaveChangesAndVerify(int expectedChangeCount),并将此参数与 的返回值等同SaveChanges()。如果值匹配,则提交事务,如果不匹配,则回滚事务。

请检查下面的代码,让我知道它是否有效以及我是否需要考虑任何事项。另外,有没有更好的方法来做到这一点

public static class DbContextExtensions
{
    public static int SaveChangesAndVerify(this DbContext context, int expectedChangeCount)
    {
        context.Database.BeginTransaction();
        var actualChangeCount = context.SaveChanges();
        if (actualChangeCount == expectedChangeCount)
        {
            context.Database.CommitTransaction();
            return actualChangeCount;
        }
        else
        {
            context.Database.RollbackTransaction();
            throw new DbUpdateException($"Expected count {expectedChangeCount} did not match actual count {actualChangeCount} while saving the changes.");
        }
    }

    public static async Task<int> SaveChangesAndVerifyAsync(this DbContext context, int expectedChangeCount, CancellationToken cancellationToken = default)
    {
        await context.Database.BeginTransactionAsync();
        var actualChangeCount = await context.SaveChangesAsync();
        if(actualChangeCount == expectedChangeCount)
        {
            context.Database.CommitTransaction();
            return actualChangeCount;
        }
        else
        {
            context.Database.RollbackTransaction();
            throw new DbUpdateException($"Expected count {expectedChangeCount} did not match actual count {actualChangeCount} while saving the changes.");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

示例用法类似于context.SaveChangesAndVerify(1)开发人员期望仅更新 1 条记录。

Ant*_*dis 5

好的,有几点。

  • 除非您禁用它,否则它SaveChanges会作为事务使用。如果任何事情失败,一切都不会改变

此外,使用context.ChangeTracker.Entries()和 从那里您可以获得更改实体的数量。所以这不需要你处理交易。还SaveChanges()只需返回受影响的行数,因此它可能无法讲述完整的故事。

一般来说,我不喜欢从项目架构的角度进行这种检查的想法,它会增加动态更改代码的复杂性,并且只会增加复杂性,而不会带来任何类型的安全性或安全性。应使用单元测试而不是此类方法来验证数据完整性和正确行为。例如,您可以添加单元测试来验证更改的行是否与您预期的相同。但这应该是测试代码。不是将交付生产的代码

但是,如果您需要这样做,请不要使用事务并在更改任何内容之前对实体进行计数,因为它要便宜得多。您甚至可以使用“便宜”的 forloop,这样您就可以记录哪些实体失败了等等。此外,由于我们正在监管您使用扩展的开发人员,这意味着开发人员可以自由使用SaveChanges()据我所知。您应该为 DbContext 创建一个新的自定义类,并仅公开这 2 个方法来保存更改。