views:

468

answers:

4

I am currently stuck in the design of this solution.

The data layer design consists of the following:

  • Recipe (parent high level object)
    • Language Detail (name, description by language) (many)
      • Headers (many)
      • Steps (many)
        • Ingredients (many)
        • Quantities (many)
        • Procedures (many)
      • Notes (many)

The challenge that I am having is how to create a data access design that will add/remove the child objects in the database when the object is populated from a WCF SaveRecipe(recipe) method?

This all stems from the management asking us to add a communications layer in our application, right now our UI is coupled to our business layer, and the BL is directly coupled to the DAL, we basically need the injection of WCF between the BL and DAL.

I have read in this thread that using L2S isn't a good idea over WCF, but since the design isn't new, we have to use this type of methodology, and then move away from it once we can refactor the heavy amounts of UI work.

+1  A: 

I like this answer from Karl on the thread you referenced:

It is better to create your own classes for the transfer of data object. Those classes, of course, would be implemented as DataContracts. In your service layer, you'd convert between the linq-to-sql objects and instances of the data carrier objects. It is tedious but it decouples the clients of the service from the database schema. It also has the advantage of giving you better control of the data that is passed around in your system.

It looks like you're going to have to refactor anyways - just as well start by refactoring out the dependency to linq2sql in your UI layer.

I don't think you have a quick and easy solution.

Terry Donaghe
+5  A: 

If you are trying to send stuff down the line with WCF I suggest you create a model of the data you want to move around your domain. As far as I've found you can't serialize IQueryable objects, but you can create a set of classes that Linq populates and then serialize that. For example:

[DataContract]
public class Recipe {

    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public string Description { get; set; }

    [DataMember]
    public List<Ingredient> Ingredients { get; set; }

}

Then fill that up with

List<Recipe> recipes = (from r in dc.recipe
                           select new Recpie {
                               Name = r.name,
                               Description = r.description,
                               Ingredients = (Linq code to make list of ingredients)
                           }).ToList();

And then sending the list down the line with WCF becomes a piece of cake.

thaBadDawg
This is a great answer, the way you are populating that list of Recipe objects is a lot cleaner than the method I use to populate objects I'm going to send over WCF. I'll have to try that.
unforgiven3
This is what I was aiming for, but the biggest problem i have now is how do I optimize child objects? For example, the list?Right now we simply Blow out the children and recreate them, as they are simple text records, but in the new design we will want the advantages of the update as needed.
Tom Anderson
+1 for the answer btw, its square advice, just need more info on the children updates.
Tom Anderson
All of my objects get inherit a base class that I use as the glue for posting back. Every set method makes a needs update field true and when I pass the list back the save routine checks to see if the children need updates.
thaBadDawg
+1  A: 

I don't recommend exposing L2S classes over WCF. Create a hierarchy of DataContract objects, and pass those over WCF. The downside of this is that you have to "deep copy" your L2S objects into your DataContract hierarchy, but the upside is that you can only include fields that are necessary and proper for transport over a network. For example, in a project I'm working on now, I pass an EmployeeData object over the network that includes most of my L2S Employee fields but excludes things like the employee's salted hash & password salt.

unforgiven3
I totally agree with this, passing the ID of the child objects is completely irrelevant to the client side application.
Tom Anderson
A: 

It could also be an idea to create classes both including and excluding child entries. I have sometimes created classes like this:

class Recipe {
    [DataMember] public string Name;
    [DataMember] public string Description;
}

class RecipeWithIngredients : Recipe {
    [DataMember] public IList<Ingredient> Ingredients;
}

Edit: inadvertedly posted before the post was finished.

erikkallen