将 DTO 映射到存储库中 Create/Add 方法的实体的位置

Where to map DTOs to Entites for Create/Add method in repository

我有一个 Web Api 应用程序,其中有 EF DB 第一实体和 DTO classes。 所以这是我的通用存储库界面 -

public interface IRepository<TEntity> where TEntity:class
    {
        IQueryable<TEntity> GetAll();
        void Create(TEntity Entity);

        TEntity GetById(int id);
        void Update(TEntity Entity);
        void Remove(int id);
    }

这是其中一项服务的 GetAll 方法实现示例 -

public class OrdersRepository : IRepository<SalesOrderHeader>
    {
        private AdventureWorksEntities db = new AdventureWorksEntities();
 public IQueryable<SalesOrderHeader> GetAll()
        {
            return db.SalesOrderHeaders;

        }

这是我的服务或 apicontroller 调用方法以及附加映射 -

public IQueryable<Orders> GetSalesOrderHeaders()
        {
            **var Orders = orderRepo.GetAll();**
            var OrderDetails = orderDetailRepo.GetAll();
            return (from so in Orders
                    select new Orders()
                    {
                        SalesOrderID = so.SalesOrderID,
                        SalesOrderNumber = so.SalesOrderNumber,
                        ShipDate = so.ShipDate.ToString(),
                        Customer = customerRepo.GetById(so.CustomerID),
                        OrderItems = (from sod in OrderDetails
                                      select new OrderItems()
                                      {
                                          SalesOrderId = sod.SalesOrderID,
                                          ProductID = sod.ProductID,
                                          Quantity = sod.OrderQty,
                                          UnitPrice = sod.UnitPrice
                                      }).Where(a => a.SalesOrderId == so.SalesOrderID).ToList()
                    });
        }

如此处所示,映射是在 apicontroller class 中完成的。同样对于存储库的 Create/Add 方法,这会发生在哪里?如果在 apicontroller 中,这是否意味着我需要访问我的 apicontroller 中的实体?如果在存储库中,那么我必须将 DTO 映射到存储库中的实体。两者似乎都可疑。这是我的 DTO class -

 public class Orders
    {
        public int SalesOrderID { get; set; }
        public string SalesOrderNumber { get; set; }

        public string ShipDate { get; set; }
        public CustomerDTO Customer { get; set; }

        public List<OrderItems> OrderItems { get; set; }

    }

实体 class 称为 SalesOrderHeaders 并且具有更多字段。

都没有。像你一样,我的代码也面临着这个困境,并决定在控制器或存储库中实现对象映射只会增加不必要的复杂性,最终会违反 DRY (Don't Repeat Yourself) 原则,并且由于使用 ORM 对项目的规模来说太过分了,我最终创建了一组扩展方法这使我能够以干净且可重复使用的方式完成工作。

这是一个示例,虽然未完成,但可以帮助您构建自己的示例:

// File: ModelExtensions.Orders.cs
public static partial class ModelExtensions
{
   public static IEnumerable<OrdersDto> MapToDto(this IEnumerable<Orders> list)
   {
      return list.select(item => item.MapToDto());
   } 

   public static OrdersDto MapToDto(this Orders order)
   {
      var dto = new OrdersDto() {
         SalesOrderID = order.SalesOrderID,
         SalesOrderNumber = order.SalesOrderNumber,
         ShipDate = order.ShipDate.ToString()
      }
   }

   public static IEnumerable<OrdersDetailsDto> MapToDto(this IEnumerable<OrderDetails> list)
   {
      return list.select(item => item.MapToDto());
   } 

   public static OrderDetailsDto MapToDto(this OrderDetails orderDetails)
   {
      var dto = new OrderDetailsDto() {
         SalesOrderId = orderDetails.SalesOrderID,
         ProductID = orderDetails.ProductID,
         Quantity = orderDetails.OrderQty,
         UnitPrice = orderDetails.UnitPrice
      }
   }
}

You can also create similar mapping functions to map from DTOs to Entities.

要使用此函数,只需包含对 namespace 的引用,其中定义了扩展方法,等等,您手头有所有映射。

Basically, the transformation would occur in the API method, since there is where the exchange (DTO/Entity or Entity/DTO) is made.

Using this method, you could use the mapping functions wherever you need it without the need to repeat (DRY principle) the logic in different places.

示例用法:

public IQueryable<Orders> GetSalesOrderHeaders()
{
    var orders = orderRepo.GetAll().MapToDto();
    var orderDetails = orderDetailRepo.GetAll();
    foreach (var ord in orders)
    {
       ord.OrderItems = orderDetails.Where(a => a.SalesOrderId == ord.SalesOrderID).MapToDto();
    }
    return orders.ToList();
}