I am working on an open source project (http://sherwood.codeplex.com/) where we want to hide the usage of DO from the core to be able to switch out the usage of DO with another storage provider if there should be users of the system that do not want to purchase / use DO. Apart from this, I do also think that it improves the all over design / architecture when we implement it this way.

Here is a bit of the structure to show what we think of:

Sheerwood.Content.Core contains basically - IClientRepository, IClient, IRecordRepository, IRecord, IMeta

Then we have Sherwood.Content.DO which implements ClientRepository, Client, Record etc. in a DO model.

Most of the project should not know about Sherwood.Content.DO and only use LINQ directly on the interfaces for querying.

Now, the problem is that these interfaces are not known by DO and thus most (all?) of the LINQ stuff does not work. I have seen that there is a MaterializedViewAttribute that maybe could be used if the interface was defined in an assembly knowing DO, but since that is not the case here, it is not usable for me. I tried to find a way to "add this attribute" in runtime by editing the DO model, but didn't find it.

I also came across InterLINQ when I looked for a solution to this, and for me it looks like it is possible to "remap" the LINQ query to the real DO objects. I do not have any experience in working with LINQ implementations, and think it will be easier to get some directions / tips from you than trying to figure out this all on my own.

Another issue is that e.g. IRecord has a property IClient Client, but the DO implementation has Client Client. To implement IRecord correctly in DO.Record, I need to put in:

IClient IRecord.Client
  get { return Client; }

A LINQ conversion would also need to understand this mapping and map a query on IRecord.Client to Record.Client.

I hope this explanation was understandable and that you are able to provide me with a solution.

This thread was imported from our support forum. The original discussion may contain more detailed answer.

asked May 27 '10 at 10:07

tmyklebust's gravatar image


One Answer:

I can list two ways of doing this:

  • Implementing LINQ query rewriter. If you may types by ~ 1-to-1 rule, this might work perfectly.

  • Relying on integrated DTO/anonymous type materialization capabilities.

Second way implies you define:

var allClients = 
  from c in Query.All<Client>()
  select new ClientDto { Name = c.Name, ...,
    Orders = 
      from o in Query.All<Order>()
      select new OrderDto { Quanity = o.Quantity, ... }

// and then you can run the following query:

var selectedClients = 
  from c in AllClient
  where Name.StartsWith(prefix)
  orderby Name
  select c;

// It is equivalent to the following one:

var selectedClients = 
  from c in Query.All<Client>()
  where Name.StartsWith(prefix)
  orderby Name
  select new ClientDto { Name = c.Name, ... };

So our query translator maintains mappings for DTOs and anonymous types in queries.

Btw, what do you think if we'll offer you a redistributable license for DO4 for this project for the cost of regular licenses you'll need? This could save you a lot of time ;)

Please contact me by e-mail, if you like the idea.

answered May 27 '10 at 11:32

Alex%20Yakunin's gravatar image

Alex Yakunin

Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview


Once you sign in you will be able to subscribe for any updates here



Asked: May 27 '10 at 10:07

Seen: 5,112 times

Last updated: May 27 '10 at 10:07

powered by OSQA