For example, I've got a root object exposed in a SOA service, say Invoice (Invoice has line items as children).

Sometimes, I need to retrieve its detail line items. I'm thinking to make it lazy loading, because it's a traffic overhead to transfer line items every time Invoice is required. But in SOA fashion, it seems unlikely. Because all it can expose are Invoice POCOs, with contain no logic. Thus I cannot attach my lazy loading logic to Invoice to instruct it to load lines items when needed.

  • 2
    Marvin, your brain is the size of a planet, how come you ask us lowly humans? :P – yannis Jan 7 '12 at 13:54

There is nothing wrong in calling a service again to get the invoice items. On service level:

  1. ServiceInvoice LoadInvoice(Guid invoiceId) will get you the invoice without the details,
  2. List<InvoiceItem> LoadDetails(Guid invoiceId) will get you the lines.

After you've done that, you've lost the OOP part and the code becomes less intuitive on client side. To correct that, you may want to add an additional abstraction layer:

class Invoice : ServiceInvoice
    public List<InvoiceItem> Lines
            return MyService.LoadDetails(this.Id);

What I would do is to implement a client library that interacts with that service and then use some proxy to provide lazy loading.

For example, your service could return Invoice POCOs and InvoiceLine POCOs in two separate calls. Now, as the user/caller/client of that service, you can have your own client library that facilitates interacting with the service from your application code. In that client library you could have an Invoice class with a proxy method get_lines() that would call again to the service, get the InvoiceLine POCOs and return those (or some more functional InvoiceLine objects)

Update: Obviously, you cannot guarantee that all systems calling your service will use that same client, so the Service should not rely or depend on having that specific client library doing the calls. But for your own application, for your own client purposes, you can have whatever client functionality you want (just like many existing classes wrapping Google Analytics APIs, etc)


Certainly you want to reduce the number of round trips. That's a realistic requirement of any SOA. That means you probably have many use cases you want to code for:

interface IInvoice
    Guid InvoiceId { get; }
    string InvoiceNumber { get; }
    string CustomerName { get; }
    decimal TotalPrice { get; }
public IEnumerable<IInvoiceSummary> FindInvoices(IInvoiceCriteria criteria);

interface IInvoiceSummary : IInvoice
    int NumberOfLineItems { get; }

public IDetailedInvoice GetInvoice(Guid invoiceId);

interface IDetailedInvoice : IInvoice
    ReadOnlyCollection<IInvoiceLineItem> LineItems { get; }

Of course if you have different use cases, you may want to change those. Perhaps you want to get unpaid invoices for a customer, but in detailed format, so maybe you have another service point that returns that special case.

So, I recommend not building lazy loading into your SOA architecture. Since lazy loading hides the number of round trips to the database, and round trips are something the programmer should always be paying attention to because they're expensive, then you shouldn't hide them.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.