C# 部分加载对象的域模型

C# 部分加载对象的域模型,c#,mvvm,domain-model,C#,Mvvm,Domain Model,假设我有一个由客户端和服务器组成的应用程序。客户端使用MVVM模式(带有WPF),而服务器只是一个WCF服务,它从数据库中获取一些数据,并将数据作为DTO对象返回给客户端。在客户机中,数据访问层将这些DTO转换为域对象,并将它们传递给模型。ViewModel使用模型获取数据(域对象)并用它填充自身 为了优化数据库性能,每个ViewModel只提供它真正需要的数据,而不提供更多数据(正如许多来源所建议的那样)。例如,假设有一个名为DbCustomer的实体,它有30个属性,还有3个与客户相关的不

假设我有一个由客户端和服务器组成的应用程序。客户端使用MVVM模式(带有WPF),而服务器只是一个WCF服务,它从数据库中获取一些数据,并将数据作为DTO对象返回给客户端。在客户机中,数据访问层将这些DTO转换为域对象,并将它们传递给模型。ViewModel使用模型获取数据(域对象)并用它填充自身

为了优化数据库性能,每个ViewModel只提供它真正需要的数据,而不提供更多数据(正如许多来源所建议的那样)。例如,假设有一个名为
DbCustomer
的实体,它有30个属性,还有3个与客户相关的不同视图:
CustomerProfileView
customerListView
CustomerThirdView
。每个视图都需要不同的数据部分:
CustomerProfileView
使用20个属性,
CustomerListView
使用10个属性,
CustomerThirdView
仅使用4个属性。对于每个视图,只从数据库中获取所需的属性并将其传递到ViewModel

现在问题出现了:我应该如何设计我的域对象来支持它?

解决方案1,一个部分加载的域对象(no go) 如果我只有一个被所有ViewModels使用的
Customer
Domain对象,它将根据请求它的ViewModel具有不同的数据。显然,这是一个不可行的方法,因为如果我必须在其他地方使用这个
Customer
对象,我无法确定它是否加载了足够的属性

例如,我可能有一个方法
GetDataStoragePath
,它应该返回描述客户私有文件路径的字符串。该方法需要属性
FirstName
LastName
SSN
IsExternalCustomer
。现在,假设
CustomerThirdView
不需要
IsExternalCustomer
,因此当
CustomerThirdView模型
请求加载
客户
模型时,它不会被加载。现在,如果我在其他地方使用这个
Customer
(它不是特定于ViewModel的对象),那么方法
GetDataStoragePath
将失败

解决方案2,三个不同的域对象 在另一个解决方案中,将有3个不同的域对象(用作数据容器)和合适的接口,然后
GetDataStoragePath
将仅依赖于此接口。例如:

public interface ICanGetDataStoragePath {
    string FirstName { get; }
    string LastName { get; }
    string SSN { get; }
    bool IsExternalCustomer { get; }
}

public CustomerProfileData : ICanGetDataStoragePath { ... } // Implements interface
public CustomerListViewData : ICanGetDataStoragPath { ... } // Implements interface
public CustomerThirdViewData { ... } // Does NOT implement interface

public class CustomerLogic : ICustomerLogic {
    public string GetDataStoragePath(ICanGetDataStoragePath customer) {...}
}
这将导致一个问题,但我认为这不是一个问题。然而,这看起来很混乱,因为我可以很容易地想象,将有20种不同的方法,具有不同的需求,这将导致20个接口(并且仅对客户而言,还有许多其他域对象)。当然,在这个简单的例子中,我可以将所有四个参数分别传递给GetDataStoragePath,但在现实生活中,还有更多必需的属性


还有其他选择吗?解决问题的最佳方法是什么?

显然,您的模型需要大量数据。为什么不制作3个模型和一个复合模型

i、 e


然后将所有始终必需的字段放入Customer类中,并将其余字段分组在一起,即在CustomerProfile类中。如果
null
,则该数据未被提取且不可用

具有30个属性的客户实体是一个简化,更现实的示例是具有10个属性的实体a、B和C。某些属性对于所有实体都是通用的(例如创建者、创建实体的标识符、CreationTime、修改器等)。有时我的域对象需要A的所有属性+B的一些属性。有时我的域对象只需要A的几个属性。有时A、B和C各有一个属性就足够了。此外,没有“始终必需的字段”这样的东西,因为不同的视图确实需要不同的数据。
public class CustomerProfile 
{
    public string Phone { get; set; }
    // other profile fields
}

public class Customer 
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string SSN { get; set; }
    public bool IsExternalCustomer { get; set; }
    public CustomerProfile Profile { get; set; }
}