DB级别一对多关系改为DTO级别一对一关系

问题描述 投票:0回答:1

我正在使用 C# 代码优先方法实现一个与订单相关的项目,代码如下。 有一个网络系统来下订单,还有其他机制来接收跟踪状态。 (订单准备、订单发货、订单收到仓库、交付等...)

也可以通过电话下单,有代理手工准备订单并快速发货。在这种情况下,它将添加当日结束的订单并按预期进行跟踪。

例如:顾客拨打电话,商店代理准备电话,无需向系统添加信息。 (但他正在将订单记录到书本中,而不是系统中) 然后快递服务来扫描跟踪标签(条形码标签)并确认订单已被提取。同时,它使用快递服务的 API 将相关信息记录到我们的跟踪表中。同样,它的每个点都有一个跟踪事件。 (如果涉及仓库,如果移交给长途运输,如果移交给航空公司运输等......) 一天结束时,有计算机操作员将所有手动订单输入系统。

public class Order //Here I mentioned only few relevant properties for making this question short.
{
 public int Id { get; set;}
 public Address CustomerAddress { get; set; }
 public string LabelNo { get; set;}

}

public class Tracking
{
 public int Id { get; set;}
 public int? OrderId { get; set; } //this is nullable since, it might received manual orders which enter to the system later.
 public Order Order{ get; set; }
 public string LabelNo { get; set;}
 public string Status { get; set;}
 public string Location { get; set;}
}

使用 get API,我需要获取订单的最后一个跟踪对象。 这是 DTO。

public class OrderDataDto
{
 public int Id { get; set;}
 public AddressDto CustomerAddress { get; set; }
 public string LabelNo { get; set;}
 public TrackingDto RecentTracking { get; set;}
}

public class TrackingDto
{
 public int Id { get; set;}
 public string Status { get; set;}
 public string Location { get; set;}
}

正如您在这个Dtos中看到的,orderDto和tackingDto之间存在一对一的联系。 (实际上这不起作用,我需要像这样做更简单)。但数据库级别的实体在订单和跟踪之间具有一对多的关系。

这是 Get 方法。

public async Task<PagedResultDto<OrderDataDto>> GetOrders(InputDto input)
 {
     try
     {
         var query = await _orderManager.GetAllOrdersAsync();
         query = DtoFilter.FilterBy<Order, OrderDataDto>(query, input.Filter);//Filter means, it comes Odata from the query string.

         var totalCount = query.Count();

         List<Order> orders = query
         .OrderBy(input.Sorting)
         .Skip(input.SkipCount)
         .Take(input.MaxResultCount)
         .ToList();

         var orderDtoList = ObjectMapper.Map<List<Order>, List<OrderDataDto>>(orders);               
         return new PagedResultDto<OrderDataDto>(totalCount, orderDtoList);
     }
     catch (Exception ex)
     {
         throw new UserFriendlyException(ex.Message);
     }
 }

这就是我最终期望的回应,

{
    "result": {
        "totalcount": 22,
        "items": [
            {
                "id": "7894652",
                "customeraddress": {
                    "name": "john",
                    "phoneno": "0123456789",
                    "address": "45/B, Spenser building, Main street, Kalundali"
                },
                "labelno": "AE01254785",
                "recenttracking ": {
                    "id": 1548,
                    "status": "order dispatched",
                    "location": "Kalundali"
                }
            },
            {
               .....................
               .....................
               .....................
            }
        ]
    }
}

还有用于 OData 查询的过滤器。

例如:如果我需要获取最近跟踪状态为“订单已发送”的订单,则查询如下,

/api/orders/order/getorders?filter=recenttracking/status eq 'order dispatched'

挑战是,数据库级别它在订单和跟踪之间具有一对多关系,而我需要使用 OrderDto 获取最后一次跟踪的输出。

任何专家都可以建议我如何通过 Odata 过滤获得像上面示例 json 这样的最终输出?

c# odata
1个回答
0
投票

为了使其以最佳方式工作,您需要转换过滤器,以便将其应用于数据存储 (DbContext) 查询。它在大多数对象映射器中本机无法工作,因为关系结构不同,因此您需要实现某种转换。

DtoFilter.FilterBy<Order, OrderDataDto>(query, input.Filter)

这就是你需要施展魔法的地方,但是你还没有发布过滤器的结构,也没有发布

DtoFilter.FilterBy()
的当前实现,因此很难建议正确的实现是什么。

一个简单的解决方案是修改架构,以便

Order
具有存储
Recent_TrackingId
的属性,并且您可以对数据库中的
Tracking
记录或 triggers 使用写入操作来维护
Recent_TrackingId
。 然后您现有的逻辑将支持您拥有的映射逻辑和您想要的过滤。

  • 这种方法的一个积极副作用是显着的read性能改进。通过在访问数据时将最近跟踪逻辑移至写入操作,它变成了在数据库和映射过程中高效的简单查找。
© www.soinside.com 2019 - 2024. All rights reserved.