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