How large is your application? There's a good chance you're overthinking this. Unless the application is a large, enterprise-grade application, the high degree of loose coupling you are advocating is probably unnecessary.
If you decide that this level of loose coupling is still necessary, create a service layer that returns "service" objects. This fulfills a similar function to View Models in MVC. You will then write code in your service layer that maps objects from your domain model to your service model.
Note that part of your struggle may be due to the fact that, while your Data Repository is returning CRUD objects, your Service Layer should be returning the result of actions. For example:
public InvoiceView GetInvoice(int invoiceID);
returns a InvoiceView
object containing whatever data you wish to expose to the public, including Name, Address, Line Items and so forth, from several different tables/objects in your domain.
public class InvoiceView
{
public int InvoiceID;
public Address ShippingAddress;
public Address BillingAddress;
public List<LineItem> LineItems;
...
}
Similarly, there will be Service Layer methods that simply performs an action and returns an object indicating the result of the action:
public TransactionResult Transfer(
int sourceAccountID, int targetAccountID, Money amount, ValidationToken token);
IMPORTANT: You'll never be able to completely decouple from your data. Your consumer will always have to have some knowledge of the data, even if it's just an object ID or UUID.
Yes, the service layer is an overhead if you don't have any business logic there. Layered architecture looks like an overhead when a layer (in your case service) is not doing much. But a layered architecture provides your loose coupling which is generally good for adapting requirements in future.
If you can guarantee that you will never need to do anything in service layer except data copy from repo to model then you can remove the service layer in your design. However if your application is basic then you don't have to worry about adding another layer for performance or other reason.
Personally I will keep the service layer and (depends on the technology) will implement a generic DAO/Repository layer.
Best Answer
If your repository layer is properly abstracted (eg, the service layer and controller can only access the repository via interfaces), then:
On balance, I'd stick with feeding everything through the service layer. But that's pure opinion; accessing the repository directly is equally valid.
If your repository layer isn't properly abstracted (ie the service layer deals directly with concrete repository/database classes), then: