4
votes

I have a service with domain model and I want expose data to clients. Service has typical architecture: database, ORM(EF), business layer with domain model.

I want to use WCF DataServices to expose data to clients, but I can't send data objects from domain model to client. I going to use DTO to interact with clients and I have dto<=>data objects mapping.

DataServices has reflection provider which seems to be fine in this case(let's consider read-only scenario). But reflection provider require IQueryable<dto> property to be exposed. And this is the problem. So I see following ways to solve it:

  1. Load all domain objects, map all of them to dtos and return result dtos. Really bad approach if there are many domain objects exists.
  2. Create a "linq2dto" provider and generate dynamically correspondent "linq2EF" query, at point of query materialization get data objects from db and perform mapping. Its sounds good, but as I see, it a complicated task.

So guys, I need help. I do not want to write(and support!) new one linq provider. May be there is somewhere some "general linq2anyware" realization which I can use?

From other hand, I really can't expose data objects to client and use DataServices EF provider. Is there some simple way to implement such mapping?

2
Just asking the obvious question first: do you really need DTOs? Code first with EF doesn't suit your needs sufficiently?Mark Stafford - MSFT

2 Answers

1
votes

In short, write each DTO manually.

May not be the answer you are looking for, but this is what I suggest. If you cannot expose the actual type, write a lightweight satellite type manually, for example

class Foo
{
    //large domain type

    FooDTO ToDTO()
    {
        return new FooDTO(...)
    }
}

class FooDTO
{
    //lightweigh
}

I haven't seen any LINQ providers that can help you to make a generic converter, but maybe it's because of my limited experience. The other argument against using generic converter is that domain types may require quite specific instructions of what to include in a lightweight object and what to exclude.

Alternatively, you may try to write a generic class that uses reflection to go through all public properties and return you an serrialised object, but then how would you know the type of an object at the other end of a wire (if you cannot use your domain type)?

1
votes

Unfortunately if you're really set on using DTOs, you will need to take on the work of performing the query tree translation to something EF can use. That most likely puts you into Custom Provider territory, which is another issue you would have to deal with.

For the query tree translation specifically, you might look at something like re-linq or IQ toolkit.

Can we have a short conversation in the comments on the question about why you need DTOs? I think this question will be more useful to others if they can understand that detail as well.