Base solution for your next web application
Starts in:
01 DAYS
01 HRS
01 MIN
01 SEC
Open Closed

Updating entity tree with deep nested entities #8164


User avatar
0
ajayak created

My app deals with saving orders received from an external system. The order contains child items like line items, address, fulfillments, refunds > refund items etc.

Currently, I use an ugly looking code to detect what has changed in each entity by its External Id. Can someone recommend me a better way? :)

Following is a simplified entity model of Order

public class Order 
{
    public long Id { get; set; }
    public string ExternalOrderId { get; set; }
    public List<LineItem> LineItems { get; set; }
    public List<Fulfillment> Fulfillments { get; set; }
    public ShippingAddress ShippingAddress { get; set; }
    public List<Refund> Refunds { get; set; }
    public string FinancialStatus { get; set; }
    public string FulfillmentStatus { get; set; }
}

public class LineItem 
{
    public long Id { get; set; }
    public string ExternalLineItemId { get; set; }
    public string SKU { get; set; }
    public int Quantity { get; set; }
    public long OrderId { get; set; }
}

public class Fulfillment 
{
    public long Id { get; set; }
    public string ExternalFulfillmentId { get; set; }
    public string Status { get; set; }
    public string TrackingUrl { get; set; }
    public long OrderId { get; set; }
}

public class ShippingAddress 
{
    public long Id { get; set; }
    public string ExternalShippingAddressrId { get; set; }
    public string Addres { get; set; }
    public long OrderId { get; set; }
}

public class Refund 
{
    public long Id { get; set; }
    public string ExternalRefundId { get; set; }
    public List<RefundedItem> LineItems { get; set; }
    public string CancelledReason { get; set; }
    public long OrderId { get; set; }
}

public class RefundedItem 
{
    public long Id { get; set; }
    public string ExternalRefundedItemId { get; set; }
    public string SKU { get; set; }
    public int Quantity { get; set; }
}

My sample code:

private async Task ManageFulfillments(long orderId, Order order)
{
    if (order.Fulfillments == null || !order.Fulfillments.Any()) return;

    var newFulfillmentIds = order.Fulfillments.Select(c => c.ExternalFulfillmentId).ToList();
    var dbFulfillments = await _fulfillmentRepository.GetAll().IgnoreQueryFilters()
        .Where(c => c.OrderId == orderId)
        .Select(c => new { c.Id, c.ExternalFulfillmentId }).ToListAsync();
    var dbFulfillmentIds = dbFulfillments.Select(c => c.ExternalFulfillmentId).ToList();

    // Delete Fulfillments that are not present in new Fulfillments list
    var deletedFulfillments = dbFulfillmentIds.Except(newFulfillmentIds).ToList();
    if (deletedFulfillments.Any())
    {
        await _fulfillmentRepository.DeleteAsync(c =>
        deletedFulfillments.Contains(c.ExternalFulfillmentId) && c.ExternalOrderId == orderId);
    }

    // Update existing Fulfillments ids
    order.Fulfillments
        .Where(c => dbFulfillmentIds.Contains(c.ExternalFulfillmentId))
        .ToList()
        .ForEach(async c =>
        {
            c.Id = dbFulfillments.Where(p => p.ExternalFulfillmentId == c.ExternalFulfillmentId)
                .Select(p => p.Id).FirstOrDefault();
            await _fulfillmentRepository.UpdateAsync(c);
        });

    // New Fulfillments will automatically be added by EF
}

I have similar code in place to update other entites as well and I'm not proud of it!


1 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team

    I can't think of other ways.