views:

3961

answers:

4

I've been coming up with a lot of dead ends on this question. Supposedly, .NET 3.5 SP1 has Support for ADO.NET Entity Framework entities in WCF contracts. But when I look for solid info on it I'm not getting a lot of answers. I found this one snippet on an MSDN thread. Does anyone have any experience with this? What happened to the [DataContract]? Is this all there is to it? Why is there so little material on this?

This the answer from Tim Mallalieu in Microsoft.

Entity Types that are generated in the Entity Framework are, by default Data Contracts. If I were to create a simple model in the Entity Designer like the following: The cart Entity Type is by default a DataContract with all properties annotated as data members. We can then use this in a WCF service as follows:

[ServiceContract]

public interface IService1

{
    [OperationContract]
    Cart[] AllCarts();
}



public class Service1 : IService1

{
    public Cart[] AllCarts() 

    {
        using (MSPetShop4Entities context = new MSPetShop4Entities())

        {
            var carts = from c in context.Carts select c;
            return carts.ToArray();
        }
    }
}

As the Entities are DataContracts you can now roll your services as you see fit and send these across the wire.

A: 

I recommend that you not return Entities directly. Unfortunately, Microsoft chose to include implementation-specific data as part of the DataContract for entities. This will not interoperate with other platforms, and is the sort of thing that might fail to interoperate even between .NET versions.

Instead, I recommend you follow the Data Transfer Object pattern and just return POCO classes that are copies of the data in the entities, with no behavior. You can return List of such classes to represent a table, etc.

John Saunders
I've considered this but the mind boggles at how much work this could incur. From the face of it, the simple code above doesn't seem to blur the separation of concerns. If I'm going to accept EF aren't I 'in for a penny, in for a pound'? In other words, I'm already out of POCO territory. No?
OK John, sorry I missed your point. You're saying that the object that's returned has 'other stuff' besides simple data. That's not good. Is there any good way you've come up with that will generate the DTO contract statements?
Part of me wants MS to offer a subset of WCF that is less interoperable, but more Data Entity, Linq, etc friendly, but then anything like that still adds coupling that I'm not sure is a good idea...
Terry Donaghe
Is there any way to see exactly what's coming back from a call? Seems to me that if EF is simply annotating the Entities and Properties using the WCF standards, how can WCF return other than the WCF standard? Does EF break WCF??
Following John's response could save you from additional problems in the future (i.e. ObjectContext). Try treating Entity Framework like a language-integrated database, and you'll be safer. http://wizardsofsmart.net/patterns/linq-to-sql-and-entity-framework-as-internal-object-databases
Ryan Riley
A: 

The "sharing interfaces and not type" tenet presupposes that you don't own both ends of the wire and/or you're writing a public-facing web service. WCF can be used (and is used) in contexts where this is decidedly not the case. Many enterprise n-tier architectures have a WCF-fronted application tier to facilitate load-balancing among other things. In these cases it is perfectly valid to share type and, in fact, is desired.

Mike Bouck
A: 

You could go the easy way and use ADO.NET Data Services.

Ryan Riley
In the end I've done exactly that. I hope it's not a mistake in the long run. The downside I'm seeing so far is that I've ended up implementing a repository pattern on the client side rather than on the model side. I'm not happy about that and will probably have to refactor later on.
The danger of ADO.NET Data Services is that it can be quite difficult to follow a DDD approach. You should treat the ADO.NET Data Services as just that: data services. If you need a stronger set of model services, you'll need to create that separately.
Ryan Riley
A: 

Some more detail in response to comments:

There are several problems with the classes generated by EF. I'm looking now at an AdventureWorks example with SalesOrderHeader and SalesOrderDetail. The SalesOrderDetail entity has both "SalesOrderHeader" and "SalesOrderHeaderReference" properties, both marked as DataMembers. This looks like a bug, since the "SalesOrderHeader" property is also marked [XmlIgnore] and [SoapIgnore].

Also, consider whether you want to serialize the link back to the parent SalesOrderHeader in the first place. Besides, what exactly should be serialized? SOAP doesn't support references in an interoperable manner.

Finally, the base classes of the entities are also data contracts. Yet they have nothing to do with the data you are returning - they are purely an implementation artifact.

In short, Microsoft screwed up on this one. They didn't think it through.

About ways to generate the DTO classes, I suggest looking into various code generation tools, like CodeSmith. You can write code to do this yourself; I did so in my previous position. The nice thing about generating the DTO is that you also get to generate the methods to translate to and from the DTO.

As to overhead, the overhead of moving some data around in memory is nothing compared to the amount of time it's going to take to send the data over a network!

John Saunders