Entity Framework 核心验证 SaveChanges 计数
Entity Framework Core verify SaveChanges count
我被分配了一项任务来验证使用 SaveChanges()
完成的更改计数。
希望 开发人员应该知道在 SaveChanges()
被调用时 之前会更改多少条记录。
为了实现它,我为 DbContext
创建了一个名为 SaveChangesAndVerify(int expectedChangeCount)
的扩展方法,我在其中使用事务并将此参数等同于 SaveChanges()
的 return 值.
如果值匹配,则提交事务,如果不匹配,则回滚事务。
请检查下面的代码,让我知道它是否有效,以及是否有任何我需要考虑的事项。另外,是否有更好的方法?
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.");
}
}
}
示例用法类似于 context.SaveChangesAndVerify(1)
,开发人员只希望更新 1 条记录。
好的,所以有几点。
- 除非您已禁用它
SaveChanges
作为事务处理。如果有任何失败,什么都不会改变
进一步使用 context.ChangeTracker.Entries()
,您可以从那里获得已更改实体的数量。所以这不需要你处理交易。另外 SaveChanges()
只是 return 受影响的行数,因此它可能无法说明全部情况。
一般来说,我不喜欢从项目架构的角度进行这种检查的想法,它增加了动态更改代码的复杂性,并且只是增加了复杂性而没有带来任何类型的安全性或安全性。应该使用单元测试而不是那些类型的方法来验证数据完整性和正确的行为。例如,您可以添加单元测试来验证更改的行是否与您预期的相同。但这应该是测试代码。不是将要交付生产的代码
但是,如果您需要这样做,请不要使用事务并在更改任何内容之前对实体进行计数,因为它要便宜得多。您甚至可以使用“便宜”的 forloop,这样您就可以记录失败的实体等等。此外,由于我们正在监管您使用扩展的开发人员,这意味着据我所知,开发人员可以自由使用 SaveChanges()
。您应该为 DbContext 创建一个新的自定义 class 并仅公开这两种用于保存更改的方法。
我被分配了一项任务来验证使用 SaveChanges()
完成的更改计数。
希望 开发人员应该知道在 SaveChanges()
被调用时 之前会更改多少条记录。
为了实现它,我为 DbContext
创建了一个名为 SaveChangesAndVerify(int expectedChangeCount)
的扩展方法,我在其中使用事务并将此参数等同于 SaveChanges()
的 return 值.
如果值匹配,则提交事务,如果不匹配,则回滚事务。
请检查下面的代码,让我知道它是否有效,以及是否有任何我需要考虑的事项。另外,是否有更好的方法?
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.");
}
}
}
示例用法类似于 context.SaveChangesAndVerify(1)
,开发人员只希望更新 1 条记录。
好的,所以有几点。
- 除非您已禁用它
SaveChanges
作为事务处理。如果有任何失败,什么都不会改变
进一步使用 context.ChangeTracker.Entries()
,您可以从那里获得已更改实体的数量。所以这不需要你处理交易。另外 SaveChanges()
只是 return 受影响的行数,因此它可能无法说明全部情况。
一般来说,我不喜欢从项目架构的角度进行这种检查的想法,它增加了动态更改代码的复杂性,并且只是增加了复杂性而没有带来任何类型的安全性或安全性。应该使用单元测试而不是那些类型的方法来验证数据完整性和正确的行为。例如,您可以添加单元测试来验证更改的行是否与您预期的相同。但这应该是测试代码。不是将要交付生产的代码
但是,如果您需要这样做,请不要使用事务并在更改任何内容之前对实体进行计数,因为它要便宜得多。您甚至可以使用“便宜”的 forloop,这样您就可以记录失败的实体等等。此外,由于我们正在监管您使用扩展的开发人员,这意味着据我所知,开发人员可以自由使用 SaveChanges()
。您应该为 DbContext 创建一个新的自定义 class 并仅公开这两种用于保存更改的方法。