WPF MVVM WCF 客户端/服务器架构

5
我想构建一个基本的wpf/mvvm应用程序,通过WCF从服务器获取数据,并允许客户端显示/操作(具有CRUD操作)此数据。
到目前为止,我考虑的架构如下:
- 一个“全局”模型层,实现验证、研究标准和INotifyPropertyChanged和服务合同。 - 一些服务层,主要是针对实体框架4个实现模型层的合同,使我能够访问和操作数据。 - 注意,我还想拥有离线数据源,比如XML或其他东西,所以我计划使用一些DI/IoC来实现另一个服务。 - WCF层 - 客户端数据存储的额外层? - ViewModel
我清楚Views/ViewModel部分,但我在理解模型、WCF和ViewModel之间的关系方面遇到了麻烦。
我的问题是:
1. 我应该如何处理由EF生成的模型?放弃它并采用代码优先方法,手动对数据库进行映射吗?
2. 对于WCF数据传输,我应该在模型中使用关系属性,即Product有一个客户,而不是一个CustomerId吗?
3. 我是否应该在WCF和ViewModel之间增加一个额外的层,用于存储和操作数据,或者直接将ViewModel插入WCF是最佳实践?
欢迎提供此类架构的任何其他提示...

你可能想阅读我对 https://dev59.com/CWkv5IYBdhLWcg3wqimS 的回答。 - Jon
@Jon:你的回答确实很棒,谢谢。然而,我对模型部分还不是完全清楚,请参考我回答给ken2k的内容。 - LaurentH
2个回答

4

有不同的解决方案来构建一个三层WPF应用程序的架构,以下是其中一种可能性:

1+2) 一种解决方案是创建“中间”对象,代表客户端应用程序实际需要的内容。 例如,如果应用程序需要显示有关产品以及相关客户姓名的信息,则可以构建以下对象:

public MyProduct
{
    // Properties of the product itself
    public int ProductID { get; set; }
    public string ProductName { get; set; }
    ...

    // Properties that come from the Customer entity
    public string CustomerName { get; set; }
}

您可以暴露一个无状态的WCF服务,通过ID返回您的产品:
[ServiceContract]
MyProduct GetProductByID(int productID);

在您的应用程序服务器端(即您服务的实现)中,您可以通过使用 EF 查询数据库来构建 MyProduct 实例(每个调用使用一个上下文),并将其返回:

public MyProduct GetProductByID(int productID)
{
    using (DBContext ctx = new ....)
    {
        return from p in ctx.Products
            where p.ID == productID
            select new MyProduct
            {
                ProductID = p.ID,
                ProductName = p.Name,
                CustomerName = p.Customer.Name  // Inner join here
            };
    }
}

3) 在WCF服务和ViewModel之间添加额外的层可能被认为是过度工程化。在我看来,直接从ViewModel调用WCF服务是可以的。 WCF生成的客户端代理代码实际上起到了您的模型的作用(至少是模型的一部分)。


编辑:

为什么MyProduct应该引用CustomerName而不是Customer? 在我的情况下,Customer将具有许多属性,我要使用这些属性。 这种“映射”是否太昂贵?

您可以使用实际的实体。但是在客户端上,由于它是三层架构,您无法通过导航属性访问DB。如果有一个嵌套的 Customer 属性(类型为 Customer),则客户端将可以访问 theProduct.Customer.Products,但是这样做没有意义,因为您无法使用此方式进行延迟加载实体(客户端上没有DB上下文)。

平铺的“中间”POCO更加简单。在这种特定操作中,没有性能问题,映射也很简单,与DB请求时间相比,CPU使用率微不足道。


谢谢。你的回答帮了我,但是我还不清楚为什么MyProduct应该引用CustomerName而不是Customer。在我的情况下,Customer会有很多我要处理的属性。这种"映射"会不会太耗费资源? - LaurentH

2
首先,一些通用信息:Jason Dollinger在Lab49上提供了一份非常好的MVVM教程。点击此处查看。 编辑 该视频涵盖了构建WPF应用程序时大部分需求。还包括依赖注入和与WCF的连接(但是在讨论WCF时没有深入探讨,但是有一种真正有效的方法来解决这里的问题)。
他开发的源代码也在此处提供。
我认为,每个涉及MVVM的人都应该看看它!
= > 1. 我应该如何处理EF生成的模型?摆脱它并采用Code First方法,手动与数据库进行映射吗?
AutoMapper可以帮助解决这个问题。AutoMapper的Codeplex页面。 您的问题似乎非常适合使用这个工具!
= > 2. 对于WCF数据传输,我应该在我的模型中有关系属性,即Product有一个Customer而不是CustomerId吗?
不要改变模型!产品ID是订单的一部分,而订单有客户ID。 坚持这一点。在服务层中,您可能最终会得到ID。 因为您可能在此处不会更改产品或客户。如果您这样做(我的订单示例不适用于此),则可以传输动态数据,而不是静态数据。
= > 3. 我应该在WCF和ViewModel之间添加一个附加层以存储和操作数据,还是将ViewModel直接插入WCF最佳实践?
在大多数情况下,我在构造函数中注入了服务层到我的ViewModel中。 这可以被认为是另一层,因为它处理WCF客户端部分并处理服务器端的“更改”事件。(行更改、新行、行删除等) 编辑 如果您必须调度服务层事件,则在WCF和ViewModel之间拥有那个小型、轻量级的层要容易得多。一旦您需要,您可能会自然地想到这样一层。

谢谢。我已经听说过Jason Dollinger的教程,现在是观看它的时候了! - LaurentH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接