C# 中的数据传输对象设计模式






4.82/5 (21投票s)
在本文中,我们将解释 C# 中的数据传输对象设计模式
目录
介绍和定义
DTO(数据传输对象)是用于在层之间移动数据的数据容器。它们也被称为传输对象。 DTO 仅用于传递数据,不包含任何业务逻辑。 它们只有简单的 setter 和 getter。
例如,下面是一个 Entity
类或一个业务类。 您可以看到它在 setter 中有业务逻辑。
class CustomerBO
{
private string _CustomerName;
public string CustomerName
{
get { return _CustomerName; }
set
{
if (value.Length == 0)
{
throw new Exception("Customer name is required");
}
_CustomerName = value;
}
}
}
上述 Customer
实体类的数据传输对象如下所示。 它将只有 setter 和 getter,这意味着只有数据,没有业务逻辑。
class CustomerDTO
{
public string CustomerName { get; set; }
}
因此,在本文中,让我们尝试了解在哪些情况下使用 DTO。
场景 1:- 提高性能
考虑以下场景。 我们有一个客户业务类和一个产品业务类。
class CustomerBO
{
private string _CustomerName;
public string CustomerName
{
get { return _CustomerName; }
set
{
if (value.Length == 0)
{
throw new Exception("Customer name is required");
}
_CustomerName = value;
}
}
}
public class ProductsBO
{
private string _ProductName;
public string ProductName
{
get { return _ProductName; }
set
{
if (value.Length == 0)
{
throw new Exception("Product Name is required");
}
_ProductName = value;
}
}
public double ProductCost { get; set; }
}
假设有一个远程客户端正在调用以获取 Customer
数据和他们购买的 Products
。 现在客户端必须进行两次调用,一次获取 Customer
数据,另一次获取 Products
数据。 现在这非常低效。 如果我们可以在一次调用中获取数据,那就太好了。
DataAccessLayer dal = new DataAccessLayer();
//Call 1:- get Customer data
CustomerBO cust = dal.getCustomer(1001);
//Call 2:- get Products for the customer
ProductsBO prod = dal.getProduct(100);
因此,为了实现相同的目的,我们可以创建一个统一的简单类,该类具有来自这两个类的属性。
class CustomerProductDTO
{
// Customer properties
public string CustomerName { get; set; }
// Product properties
public string ProductName { get; set; }
public double ProductCost { get; set; }
}
您现在可以在一次操作中获取 Customer
和 Product
数据。
//Only one call
CustomerProductDTO cust = dal.getCustomer(1001);
WCF 和 Web 服务中的代理对象是提高性能的数据传输对象的良好候选者。
场景 2:- 扁平化对象层次结构
我最终使用 DTO 对象的第二个场景是扁平化对象层次结构,以便于数据传输。
例如,您有一个客户业务类,它与地址类具有一对多的关系。 但是现在假设我们要将所有这些数据写入 CSV 文件或跨层传输。 在这些情况下,扁平化的非规范化结构使事情变得更容易。
因此,您有一个 customer
类,它与 address
对象具有一对多的关系。 它也有业务规则。
class CustomerBO
{
// Customer properties removed for reading clarity
public List<addressbo> Addresses { get; set; }
}
class AddressBO
{
private string _Address1;
public string Address1
{
get { return _Address1; }
set
{
if (value.Length == 0)
{
throw new Exception("Address is required");
}
_Address1 = value;
}
}
}
要创建上述 customer
和 address
类的 DTO,我们可以简单地将这两个类的属性合并到一个类中,并排除业务逻辑。
class CustomerDTO
{
public string CustomerName { get; set; }
public string ProductName { get; set; }
public double ProductCost { get; set; }
}
场景 3:- 排除属性
由于 DTO 完全独立于主业务对象,因此您可以自由删除某些您不想传输到其他层的字段。 例如,下面是一个简单的客户业务对象类,它有两个名为“IsAdmin
”和“CustomerName
”的属性。
当您将此业务对象传递到 UI 层时,您不希望将“IsAdmin
”值传输到 UI。
class CustomerBO
{
private bool _IsAdmin;
public string IsAdmin
{
get { return _IsAdmin; }
}
private string _CustomerName;
public string CustomerName
{
get { return _CustomerName; }
set
{
if (value.Length == 0)
{
throw new Exception("Customer name is required");
}
_CustomerName = value;
}
}
}
因此,您可以创建一个仅具有“CustomerName
”属性的 DTO。
class CustomerDTO
{
public string CustomerName { get; set; }
}
DTO 和业务对象之间的区别
业务对象 | DTO | |
Data | 是 | 是 |
业务逻辑 | 是 | 否 |
结构 | 规范化 | 规范化或非规范化 |
如果我们能用数学方式总结一下
Business object = Data + Logic
DTO = Data
如果您想学习设计模式,我建议您通过项目学习设计模式。 不要单独学习每个设计模式。 因为当设计模式在项目中使用时,它们会相互重叠,而这种体验只能通过做一个实际的项目并按需和自然地实现设计模式来感受到。
进一步阅读,请观看下面的面试准备视频和分步视频系列。