How do you Expose Inherited Entities using WCF and OData? - wcf

If I have an OData inheritance hierarchy exposed by WCF data services how do I expose the subclass entity as its own entity set? What URI should I use to access it?
Let's say I have an OData URL as follows:
http://myodataservice.svc
Let's say I have an entity foo that is abstract and an entity bar that is a subclass of foo.
What I'd like to do is go to a URL http://myodataservice.svc/bar to access the bar object but it seems that this is not possible. Can anyone point me at a simple example so I can see how this works?

Each entity instance can only belong to one entity set. So you can have multiple entity sets which share the same type (or base type), but their sets of entity instances must not overlap.
If you need to have an entity set which contains all the entity instances of the base type, but still want to sometime access only entity instances of a certain derived type, you can use the type cast path segment.
This requires OData V3, but then you can do something like this:
http://myodataservice.svc/baseentities/Namespace.DerivedType
This URL acts like an entity set of entities from the baseentities entity set, but filtered to only the DerivedType instances. It is also strongly typed (the type of that URL is a collection of DerivedType instances). So you can use it just like any other entity set URL, that is you can further navigate using / or you can append any of the query operators like $filter, $select and so on.

Related

How to stop wcf service generating entity framework references

I have a WCF service containing an entity framework project.
I also have DTO classes that I use to expose the data. The entity objects get mapped to DTO objects.
When I generate a service proxy I am seeing both the entity object and the DTO object.
If I have a table called Product I get a Product and a Product1 reference.
This didn't use to happen.
What have I done to cause this and how can I stop my entity objects being exposed?
More Info:
When EF generates a model object from the database, it adds a data contract attribute like this:
[EdmEntityTypeAttribute(NamespaceName="KernMobile_V5Model", Name="JobMaster")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
public partial class JobMaster : EntityObject
I assume this means that it will be exposed by the service?
The service only exposes objects that are used in the service operations, or are specified as a known type to be exposed.
If your client proxy is generating an object for these entity framework objects, you must be exposing them through your service somehow. This can be as request or response objects, or as properties on those objects.

Return Entity Framework objects from WCF

I am working on a WCF service to provide data to multiple mobile clients. Data model is Entity Framework 4.0. Schema is given below.
When i returnt he object of SysUser the result also contains the navigation properties and EntityKey and other EF related stuff. Is it possible that i get the pure object(only the database fields without the relationship etc).
Thanks
Update
the exception occures "Only parameterless constructors and initializers are supported in LINQ to Entities." on followign code:
return (from u in DataSource.SysUsers
where u.UserID == UserID
select new Player(u)
).FirstOrDefault();
You probably want to send DTOs across the wire rather than your EF objects.
You could use something like AutoMapper to populate your DTOs from the EF objects.
I think if you remove the virtual keyword in your SysUser model for the navigation properties, those will not be loaded. Later, if you need to load this properties, you can do it manually as stated here: http://msdn.microsoft.com/en-us/data/jj574232
Now, if you want to make SysUser travel through a WCF service, it is not a good idea. First, your service's client will need a reference to your Models Project... and that doesn't feels right. If you don't reference your Models, you will get a proxy for it, that is more or less the same as Joe R explained about DTOs.
Here is a related answer: https://stackoverflow.com/a/7161377/7720

Database entity exposed as object in WCF service

I have a WCF service in which I have a method which returns an IQueryable of an object representing a database table (Accommodation) using Entity Framework. When I try and use that method on the client side the method does not return IQueryable but object. I looked at the code for the service and the Accommodation class that Entity Framework generates has this attribute
[DataContractAttribute(IsReference=true)]
So, AFAIK the client should be able to see that class. What is going wrong here?
Thanks,
Sachin
The type will only appear in the metadata if it is used on the contract. The metadata has no idea what IQueryable is - its a definition of behavior whereas the contract only defines state so the generated code will use somethingit does understand in this situation - i.e. object
It is really not a good idea to use the EF generated types on your service contract - you, in effect, tightly couple your service consumers to your data access layer. Use EF internally in the service and use types which define the data you want to pass around on the service boundary

WCF and Inheritance

I'm working on a project where I have an abstract class of Appointment. There are Workouts, Meals and Measurements that all derived from Appointment. My architecture looks like this so far:
Dao - with data access layer being entity framework 4 right now
POCO classes using the T4 templates
WCF
Silverlight Client, ASP.net MVP, mobile clients
Would I put business rules in the POCO class? or map my Entities to a business object with rules and then map those to DTOs and pass those through WCF?? and when I pass the DTOs do I pass over type Appointment? Or write a service method for each sub class like Workout or Meal?
I haven't found any good material using table per type inheritance and WCF.
thanks in advance!
-ajax
it mainly depends on complexity you require. You are using POCO classes it is good starting point. You now have to choose how complex application are you going to build, how much business logic do you want to add and what do you want to expose to your clients?
The POCO entity can be just DTO or you can turn POCO entity into business object by adding business methods and rules directly into that entity - you will transform the entity into Active record pattern or to Domain object. I don't see any reason to map your POCOs to another set of business objects.
Exposing POCO entity in WCF service is the simplest way. You can use operations which will works directly with Appointment class. Additionally you have to give your service information about all classes derived from Appointment - check KnownTypeAttribute and ServiceKnownTypeAttribute. Using entity often means that service calls transport more than is needed - this can be problem for mobile clients with slow internet connection. There is one special point you have to be aware of when exposing entity which is aggregation root (contains references to another entitities and collection of entities) - if you don't have full control over client applications and you allow clients sending full modified object graph you have to validate not only each entity but also that client changed only what he was allowed to. Example: Suppose that client want to modify Order entity. You send him Order with all OrderItem entities and each item will have reference to its Product entity = full object graph. What happens if instead of modifing Order and OrderItems client changes any of Products (for example price)? If you don't check this in your business logic exposed by WCF and pass the modified object graph into EF context, it will modify the price in your database.
If you decide to use your entities like business objects you usually don't expose those entities, instead you will create large set of DTOs. Each operation will work with precisely defined DTO for request and response. That DTO will carry only information which are really needed - this will reduce data payload for service calls and avoid passing modified prices of product, because you will simply define your DTO to not transfer price or even whole product from the client. This solution is much more time consuming to implement and it adds additional layer of complexity.
Because I have mentioned object graphs I must clarify that there is another hidden level of complexity when using them: change tracking. EF context needs to know what have changed in object graph (at least which OrderItem was modified, which was added or deleted, etc.) for correct persistence. Tracking and multi tier solution is a chalenge. The simplest solution does not track changes and instead uses additional query to EF. This query returns actual persisted state of object graph and modified object graph is merged with it (special care is needed for concurrency checks). Other solutions uses some tracking support in entity - check Tracking changes in POCO and Self-tracking entities. But this is only for entities. If you want to track changes in DTO you have to implement your own change tracking. You can also read articles from MSDN magazine about multi tier applications and EF:
Anti-Patterns To Avoid In N-Tier Applications;
Building N-Tier Apps with EF4

EDM -> POCO -> WCF (.NET4) But transferring Collections causes IsReadOnly set to TRUE

Ok, this may sound a little 'unorthodox', but...using VS2010 and the new POCO t4 template for Entity Framework (Walkthrough: POCO Template for the Entity Framework), I can generate nice POCO's. I can then use these POCO's (as DTO's) in a WCF service essentially going from EDM all the way through to the client. Kinda what this guys is doing (POCO with EF 4.0 and WCF 4.0), except everything is generated automatically. I understand that an entity and a DTO 'should' be different, but in this case, I'm handling client and server, and there's some real advantages to having the DTO in the model and automatically generated.
My problem is, that when I transfer an entity that has a relationship, the client generated collection (ICollection) has the read-only value set, so I can't manipulate that relationship. For example, retrieving an existing Order, I can't add a product to the Products collection client-side...the Products collection is read-only.
I would prefer to do a bunch of client side 'order-editing' and then send the updated order back rather than making dozens of server round trips (eg AddProductToOrder(product)). I'd also prefer not to have a bunch of thunking between Entity and DTO. So all-in-all this looks good to me...except for the read-only part.
Is there a solution, or is this too much against the SOA grain?
The FixupCollection which is assigned to your ICollection is recreated as an Array when the deserialization occurs. Th'at's why your Products collection is read-only.
In order to modify this, you can use the option (existing at least on VS2010) in the "Add Service Reference", to change the Collection type to something else (Generic.List or Generic.Observable).
But, if you use the option to reuse type existing in existing assembly and referencing the assembly containing your entity, the previous option will not be applied to existing type and you will still have Array in your Products collection.
A workaround i use (only if you reuse type on client side and reference your entity assembly) is to modify the T4 template to check if the collection is read-only in the get of Products, and set an FixupCollection if it does:
if (<#=code.FieldName(navProperty)#>.IsReadOnly)
{
var newCollection = new FixupCollection<<#=code.Escape(navProperty.ToEndMember.GetEntityType())#>>(<#=code.FieldName(navProperty)#>);
newCollection.CollectionChanged += Fixup<#=navProperty.Name#>;
<#=code.FieldName(navProperty)#> = newCollection;
}
"la mouette" solution works with referenced assemblies:
We have the same problem, and we have noticed that the property IsReadOnly is setted to true after wcf serialization (Before that, the property value is false).
We have referenced assemblies. In the workaround proposed by "la mouette", use a parametrized constructor, but our POCO template doesn't have one.
We have modified the tt creating an empty constructor to invoke the base one, and that do the trick.