[英]Translating Entity Framework model navigation properties into DTOs
我目前正在开发一个n层Web项目。 在研究了数据传输对象及其优点之后,我们决定采用这种模式。 我们的ASP.NET MVC网站无法直接访问EF DbContext,而是使用DTO发送和接收实体数据。 将有一个服务/映射层将在DTO和实体模型之间进行转换。
我的问题是,将实体模型导航属性转换为DTO的最佳方法是什么?
以下是项目中实体模型及其DTO的示例:
实体模型:
public class Payment
{
public int ID { get; set; }
public DateTime? PaidOn { get; set; }
public decimal Amount { get; set; }
public string Reference { get; set; }
//Navigation Properties
public virtual PaymentMechanism PaymentMechanism { get; set; }
public virtual ICollection<Order> Orders { get; set; }
}
DTO:
public class PaymentDto
{
public int ID { get; set; }
public DateTime? PaidOn { get; set; }
public decimal Amount { get; set; }
public string Reference { get; set; }
//--------Navigation Properties - Object Ids--------
public int PaymentMechanismId { get; set; }
public ICollection<int> OrderIds { get; set; }
}
可以看出,除导航属性外,它们非常相似。 我已将它们更改为保存整数ID(实体),而不是实体模型。 因此,如果需要获取导航属性实体,则它们的Id可以传递到服务/映射层函数,该函数将从当时数据库中检索实体,将它们映射到DTO并返回集合。 这是一种可接受的做事方式吗?
我是这个领域的新手,所以我的一些术语可能不完全正确,但希望你能理解我所得到的。 如果您需要我澄清或提供任何其他详细信息,请告诉我。
您可以使用投影加载DTO:
var paymentDtos = context.Payments
.Where(p => p.Amount >= 1000m) // just an example filter
.Select(p => new PaymentDto
{
ID = p.ID,
PaidOn = p.PaidOn,
Amount = p.Amount,
Reference = p.Reference,
PaymentMechanismId = p.PaymentMechanism.ID,
OrderIds = p.Orders.Select(o => o.ID)
})
.ToList();
您必须将dto中的OrderIds
声明为IEnumerable<int>
,而不是ICollection<int>
来进行此编译。
我不确定这个密钥集合是否真的有用。 如果您想稍后加载订单,您可以根据Payment
的ID
在单独的服务方法中执行此操作,如下所示:
public IEnumerable<OrderDto> GetPaymentOrders(int paymentID)
{
return context.Payments
.Where(p => p.ID == paymentID)
.Select(p => p.Orders.Select(o => new OrderDto
{
ID = o.ID,
//etc. mapping of more Order properties
}))
.SingleOrDefault();
}
我通常在这种情况下使用Automapper。 我将创建一个Dto类形成我的主要实体,并为我的导航属性实体创建Dto,然后让Automapper自动执行映射,而无需手动编写映射代码。
public class PaymentDto
{
public int ID { get; set; }
public DateTime? PaidOn { get; set; }
public decimal Amount { get; set; }
public string Reference { get; set; }
//Navigation Properties
public virtual PaymentMechanismDto PaymentMechanism { get; set; }
public virtual ICollection<OrderDto> Orders { get; set; }
}
public class PaymentMechanismDto
{
//properties
}
public class OrderDto
{
//properties
}
public class MappingProfile : Profile
{
public MappingProfile()
{
Mapper.CreateMap< Payment, PaymentDto >();
Mapper.CreateMap< PaymentMechanism, PaymentMechanismDto >();
Mapper.CreateMap< Order, OrderDto >();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.