Linq to Entities & WPF - 仅保存与视图相关的实体
Linq to Entities & WPF - save only entities related to a view
[编辑]
我正在寻找一种在 WPF (MVVM) 应用程序中实现 Linq To Entities 并使每个视图(或视图模型)负责单独管理其底层实体的方法。
下面是一个简单结构的例子以及我想要实现的目标:
[客户] (1..1) <----> (0..* ) [订单] ( 0..* ) <-- [订单行] --> (1..* ) [产品]
第一次查看显示客户列表
- 加载所有客户但不加载他们的订单
- 允许创建或删除客户
第二个视图 显示客户的详细信息及其订单列表
- 允许更新客户的属性
- 加载特定客户的所有订单,但不加载 orderLines
- 允许创建或删除订单
- 可能有多个视图分别管理多个客户。
第三视图显示订单详情和订单行列表
- 允许更新订单的属性
- 加载特定订单的所有订单行,以及与这些订单行相关的所有产品
- 允许创建或删除订单行
- 可能有多个视图分别管理多个订单。
第四个视图 显示产品的详细信息
- 允许更新产品的属性
- 相关产品可能已被第三个视图加载
- 可能会同时打开多个视图并分别管理各自的产品。 我不想一次更新所有产品,只想更新视图的相关产品。
根据 Microsoft 的建议,每个视图实例(或 viewModel 实例)必须有一个 DbContext 实例 (https://msdn.microsoft.com/en-us/data/jj729737.aspx)。
上面的方案当然已经很简化了。在实际应用中,我们将拥有更多的实体和视图。此外,它们可能是打开视图的不同流程,因此很难提前知道打开新视图时已经从数据库加载了哪些实体。
仍然有一个原则:视图(或相应的 ViewModel)应该负责更新它显示的实体集,而不要求 DbContext 更新另一个视图处理的实体。
问题
productView 的 DbContext 应该能够将相关产品的更改推送到数据库。但是,如果产品之前已经加载(即通过与 orderLinesView 相关联的 DbContext),则不应从数据库加载产品。问题是,据我所知,DbContext 封装了一个事务,这让我认为它几乎不能负责保存它没有自行加载的实体。如何解决此类问题?
很明显,每个视图实例都必须有一个 DbContext 实例,以便 SaveChanges() 仅处理当前视图的数据。不清楚的是天气我应该有几个继承 DbContext 的 class 或一个代表应用程序 DbContext 的 class。
是否有必要在 DbContext 上为我们要更新的每个实体类型添加一个 DbSet<> 属性?随着应用程序随着新实体的增长,DbContext 似乎需要一直更改。此外,这意味着 viewModel 中的重复代码指出应该加载哪个 DbSet<>,等等。
如果有一种机制 (1) 可以接收一组要更新的实体(无论它们的类型如何),另一种机制 (2) 允许 select 一组实体通过机制(1)?第二种机制可以是手动的(对于灵活的场景)或自动的(例如通过查看 ViewModel 中列出的所有实体)。
如果我想把数据库访问机制放在一个web服务中,我该如何继续分别管理它们每个视图的底层实体?在这种情况下,应该在哪里以及如何实例化 DbContexts?
我期待您能提供任何建议。
您可以实施类似于 Unit of Work and Repository Pattern
通过这种方式,您可以将对数据库执行的更改作为工作的一部分(window 在您的情况下)与其他工作分开。如果您对所有这些都使用相同的上下文,这将变得很复杂。
编辑:尝试回答您的一些问题:
1) 只要下一个视图不改变其他视图中的实体,您就可以将 DTO 传递给它以获取它们的逻辑。但是,如果您基于登录的数据已更改,这可能会导致一些并发问题。如果不一次保存所有相关实体,就没有简单的方法可以解决这个问题。在这些情况下,您可以尝试创建自己的缓存并使用它而不是查询 DbContext,但这同样可能是多个用户的问题。
2 和 3) 查看我上面提到的工作单元和存储库模式。这应该是一个很好的包装器,以避免重复代码。
4) 对于 Web 服务,您应该为每个请求创建一个 DbContext,否则您可能会再次遇到并发问题。在这里有一个缓存也可以提高性能。
[编辑]
我正在寻找一种在 WPF (MVVM) 应用程序中实现 Linq To Entities 并使每个视图(或视图模型)负责单独管理其底层实体的方法。
下面是一个简单结构的例子以及我想要实现的目标:
[客户] (1..1) <----> (0..* ) [订单] ( 0..* ) <-- [订单行] --> (1..* ) [产品]
第一次查看显示客户列表
- 加载所有客户但不加载他们的订单
- 允许创建或删除客户
第二个视图 显示客户的详细信息及其订单列表
- 允许更新客户的属性
- 加载特定客户的所有订单,但不加载 orderLines
- 允许创建或删除订单
- 可能有多个视图分别管理多个客户。
第三视图显示订单详情和订单行列表
- 允许更新订单的属性
- 加载特定订单的所有订单行,以及与这些订单行相关的所有产品
- 允许创建或删除订单行
- 可能有多个视图分别管理多个订单。
第四个视图 显示产品的详细信息
- 允许更新产品的属性
- 相关产品可能已被第三个视图加载
- 可能会同时打开多个视图并分别管理各自的产品。 我不想一次更新所有产品,只想更新视图的相关产品。
根据 Microsoft 的建议,每个视图实例(或 viewModel 实例)必须有一个 DbContext 实例 (https://msdn.microsoft.com/en-us/data/jj729737.aspx)。
上面的方案当然已经很简化了。在实际应用中,我们将拥有更多的实体和视图。此外,它们可能是打开视图的不同流程,因此很难提前知道打开新视图时已经从数据库加载了哪些实体。
仍然有一个原则:视图(或相应的 ViewModel)应该负责更新它显示的实体集,而不要求 DbContext 更新另一个视图处理的实体。
问题
productView 的 DbContext 应该能够将相关产品的更改推送到数据库。但是,如果产品之前已经加载(即通过与 orderLinesView 相关联的 DbContext),则不应从数据库加载产品。问题是,据我所知,DbContext 封装了一个事务,这让我认为它几乎不能负责保存它没有自行加载的实体。如何解决此类问题?
很明显,每个视图实例都必须有一个 DbContext 实例,以便 SaveChanges() 仅处理当前视图的数据。不清楚的是天气我应该有几个继承 DbContext 的 class 或一个代表应用程序 DbContext 的 class。
是否有必要在 DbContext 上为我们要更新的每个实体类型添加一个 DbSet<> 属性?随着应用程序随着新实体的增长,DbContext 似乎需要一直更改。此外,这意味着 viewModel 中的重复代码指出应该加载哪个 DbSet<>,等等。 如果有一种机制 (1) 可以接收一组要更新的实体(无论它们的类型如何),另一种机制 (2) 允许 select 一组实体通过机制(1)?第二种机制可以是手动的(对于灵活的场景)或自动的(例如通过查看 ViewModel 中列出的所有实体)。
如果我想把数据库访问机制放在一个web服务中,我该如何继续分别管理它们每个视图的底层实体?在这种情况下,应该在哪里以及如何实例化 DbContexts?
我期待您能提供任何建议。
您可以实施类似于 Unit of Work and Repository Pattern
通过这种方式,您可以将对数据库执行的更改作为工作的一部分(window 在您的情况下)与其他工作分开。如果您对所有这些都使用相同的上下文,这将变得很复杂。
编辑:尝试回答您的一些问题:
1) 只要下一个视图不改变其他视图中的实体,您就可以将 DTO 传递给它以获取它们的逻辑。但是,如果您基于登录的数据已更改,这可能会导致一些并发问题。如果不一次保存所有相关实体,就没有简单的方法可以解决这个问题。在这些情况下,您可以尝试创建自己的缓存并使用它而不是查询 DbContext,但这同样可能是多个用户的问题。
2 和 3) 查看我上面提到的工作单元和存储库模式。这应该是一个很好的包装器,以避免重复代码。
4) 对于 Web 服务,您应该为每个请求创建一个 DbContext,否则您可能会再次遇到并发问题。在这里有一个缓存也可以提高性能。