Linq to Entities& WPF - 仅保存与视图相关的实体

时间:2015-03-09 16:02:30

标签: c# linq entity-framework save instance

[EDITED]

我正在寻找一种在WPF(MVVM)应用程序中实现Linq To Entities的方法,并使每个View(或ViewModel)负责分别管理其底层实体。

以下是一个简单结构的例子以及我想要实现的目标:

[客户](1..1)< ----> (0 .. *)[订单](0 .. *)< - [ OrderLine ] - > (1 .. *)[产品]

第一个视图显示客户列表

  • 加载所有客户,但不加载订单
  • 允许创建或删除客户

第二个视图显示客户的详细信息及其订单列表

  • 允许更新客户的属性
  • 加载特定客户的所有订单,但不加载orderLines
  • 允许创建或删除订单
  • 可能有多个视图分别管理多个客户。

第三个视图显示订单的详细信息和订单行列表

  • 允许更新订单的属性
  • 加载特定订单的所有orderLines,以及与这些orderLines相关的所有产品
  • 允许创建或删除orderLines
  • 可能有多个视图分别管理多个订单。

第四个视图显示产品的详细信息

  • 允许更新产品的属性
  • 相关产品可能已由第三个视图加载
  • 可能会同时打开多个视图并分别管理自己的产品。 我不想一次更新所有产品,只想更新视图的相关产品。

根据Microsoft的建议,每个视图实例(或viewModel实例)(https://msdn.microsoft.com/en-us/data/jj729737.aspx)必须有一个DbContext实例。

上述方案当然非常简化。在实际应用中,我们将拥有更多的实体和视图。另外,它们可能是打开视图的不同流程,这使得在打开新视图时很难预先知道哪些实体已从数据库加载。

仍然有一个原则:视图(或相应的ViewModel)应该负责更新它显示的实体集,而不要求DbContext更新另一个视图处理的实体。

问题

  1. productView的DbContext应该能够将相关产品的更改推送到数据库。但是,如果先前已加载产品(即通过与orderLinesView关联的DbContext),则不应从数据库加载产品。问题在于,正如我所理解的那样,DbContext封装了一个事务,这使得我认为很难负责保存它本身没有加载的实体。如何解决这个问题?

  2. 很明显,每个视图实例都必须有一个DbContext实例,以便SaveChanges()只处理当前视图的数据。目前尚不清楚的是天气我应该有几个继承DbContext的类或一个代表应用程序DbContext的类。

  3. 是否需要添加DbSet<>我们想要更新的每个权利类型的DbContext上的属性?随着应用程序随新实体的增长,似乎DbContext需要随时更改。另外,这意味着viewModels中的重复代码指出哪个DbSet<>应该加载等 拥有一个可以接收一组实体进行更新的机制(1)(无论其类型),以及允许选择一组实体传递给机制的另一种机制(2)不是更有效(1) )?第二种机制可以是手动(对于灵活方案)或自动(通过查看ViewModel中列出的所有实体)。

  4. 如果我想将数据库访问机制放在Web服务中,我该如何继续单独管理每个视图的基础实体?在这种情况下,应该在何处以及如何实例化DbContexts?

  5. 我期待您提出的任何建议。

1 个答案:

答案 0 :(得分:0)

您可能正在实施类似Unit of Work and Repository Pattern

的内容

通过这种方式,您可以将对数据库执行的更改作为工作(您的案例中的窗口)的一部分与其他工作分开。如果对所有这些使用相同的上下文,那将会很复杂。

编辑:试着回答你的一些问题:

1)只要下一个视图不会改变其他视图中的实体,您就可以将DTO传递给它以获取它们的逻辑。但是,如果您登录的数据发生了变化,这可能会导致一些并发问题。没有简单的方法可以解决这个问题,而无需一次性保存所有相关的实体。您可以尝试创建自己的缓存并使用它而不是在这些情况下查询DbContext,但这又可能是多个用户的问题。

2和3)看看我上面提到的工作单元和存储库模式。这应该是一个很好的包装器,以避免重复代码。

4)对于Web服务,您应该为每个请求创建一个DbContext,否则您可能会再次遇到并发问题。在这里拥有缓存也可以提高性能。