将 EF Core 与 WPF 一起使用,当用户在对话框中按“取消”而不是“确定”时,我想恢复到初始状态,这可能吗?如何实现?
Using EF Core with WPF and I'd like to revert to initial state when a user press Cancel instead of OK on a dialog, is that possible and how?
我正在将 EF Core 与 WPF 一起使用,当用户在对话框中按下取消而不是确定时,我想将对任何对象所做的任何更改恢复到它们的初始状态,这可能吗?如何实现?
我正在使用全局单例 DbContext,在应用程序开始时加载我的所有数据模型。我不想知道我是否应该使用 DataContext 单例。
当用户必须对数据库中的实例进行一些更改时,我会显示一个 WPF 对话框,用户可以在其中选择“确定”或“取消”。好的,我只是做 ctx.SaveChanges()。但是对于 Cancel,我怎样才能恢复所有更改?如何返回所有对象 returns 到调用对话框时的初始状态?
我可以处理 DataContext(这将刷新所有更改)并再次重新加载所有内容,但这会花费很多时间,应该有更好的方法通过使用 DbContext 跟踪的更改来更有效地完成任务?
我找到 GitHub-dotnet/efcore 个请求:Implement RejectChanges() in DbContext #14594。但似乎没有任何解决办法?
我认为正确的解决方案应该接近 EF(非核心)的这个答案:DbContext discard changes without disposing。我会尝试对其进行编码(如果可能的话),但是一个已经正确编码并经过调试的解决方案会非常棒!
更新2022-05-27
经过几次试验和错误(例如拥有单例上下文)后,我决定采用需要更多工作但更符合 EF Core 理念的东西。就我而言,我使用“NoTracking”将完整模型(几乎)加载到内存中。然后当我想编辑一个实例(实体)时,我通过复制它并在副本上进行修改来做到这一点。如果用户选择应用修改,那么我打开一个上下文并附加到要编辑的实体,将更改应用到原始实体(从副本复制更改),然后 Ctx.SaveChanges 然后 Dispose().
问:这可能吗?如何实现?
答:当然可以。
最直接的方法是仅在“完成”(当用户单击“确定”时)时“SaveChanges()”。
另一种方法可能是制作 原始对象的副本,然后对副本执行 in-process 操作。
如果您不断更新并保存 work-in-progress 到数据库(可能是不明智的设计),那么您还可以利用 transactions,并在用户点击时回滚[取消].
示例:
https://docs.microsoft.com/en-us/ef/core/saving/transactions
using var context = new BloggingContext();
using var transaction = context.Database.BeginTransaction();
try
{
context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
context.SaveChanges();
context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/visualstudio" });
context.SaveChanges();
var blogs = context.Blogs
.OrderBy(b => b.Url)
.ToList();
// Commit transaction if all commands succeed, transaction will auto-rollback
// when disposed if either commands fails
transaction.Commit();
}
catch (Exception)
{
// TODO: Handle failure
}
您可以使用 ChangeTracker 检索所有跟踪的 EntityEntries。每个 EntityEntry 都包含所有属性的 CurrentValues 和 OriginalValues。
Documentation
我正在将 EF Core 与 WPF 一起使用,当用户在对话框中按下取消而不是确定时,我想将对任何对象所做的任何更改恢复到它们的初始状态,这可能吗?如何实现?
我正在使用全局单例 DbContext,在应用程序开始时加载我的所有数据模型。我不想知道我是否应该使用 DataContext 单例。
当用户必须对数据库中的实例进行一些更改时,我会显示一个 WPF 对话框,用户可以在其中选择“确定”或“取消”。好的,我只是做 ctx.SaveChanges()。但是对于 Cancel,我怎样才能恢复所有更改?如何返回所有对象 returns 到调用对话框时的初始状态?
我可以处理 DataContext(这将刷新所有更改)并再次重新加载所有内容,但这会花费很多时间,应该有更好的方法通过使用 DbContext 跟踪的更改来更有效地完成任务?
我找到 GitHub-dotnet/efcore 个请求:Implement RejectChanges() in DbContext #14594。但似乎没有任何解决办法?
我认为正确的解决方案应该接近 EF(非核心)的这个答案:DbContext discard changes without disposing。我会尝试对其进行编码(如果可能的话),但是一个已经正确编码并经过调试的解决方案会非常棒!
更新2022-05-27
经过几次试验和错误(例如拥有单例上下文)后,我决定采用需要更多工作但更符合 EF Core 理念的东西。就我而言,我使用“NoTracking”将完整模型(几乎)加载到内存中。然后当我想编辑一个实例(实体)时,我通过复制它并在副本上进行修改来做到这一点。如果用户选择应用修改,那么我打开一个上下文并附加到要编辑的实体,将更改应用到原始实体(从副本复制更改),然后 Ctx.SaveChanges 然后 Dispose().
问:这可能吗?如何实现?
答:当然可以。
最直接的方法是仅在“完成”(当用户单击“确定”时)时“SaveChanges()”。
另一种方法可能是制作 原始对象的副本,然后对副本执行 in-process 操作。
如果您不断更新并保存 work-in-progress 到数据库(可能是不明智的设计),那么您还可以利用 transactions,并在用户点击时回滚[取消].
示例:
https://docs.microsoft.com/en-us/ef/core/saving/transactions
using var context = new BloggingContext(); using var transaction = context.Database.BeginTransaction(); try { context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" }); context.SaveChanges(); context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/visualstudio" }); context.SaveChanges(); var blogs = context.Blogs .OrderBy(b => b.Url) .ToList(); // Commit transaction if all commands succeed, transaction will auto-rollback // when disposed if either commands fails transaction.Commit(); } catch (Exception) { // TODO: Handle failure }
您可以使用 ChangeTracker 检索所有跟踪的 EntityEntries。每个 EntityEntry 都包含所有属性的 CurrentValues 和 OriginalValues。 Documentation