Entity Framework, Derived Types, with OData feeds
-
יום רביעי 06 יולי 2011 21:00
Hello, its difficult to figure out where this question should be posted because it is related to a mix of different technologies.
I have an EntityFramework data model containing a Person, Patient, Doctor. Patient and Doctor inherit from Person via Table-Per-Type. When this inheritance is defined in EF, and when code is generated using the DbContext templates, no collections are exposed for Patients and Doctors. One must use the Persons.OfType<Patient> syntax to query for specific patients.
The problem is that when one exposes the model as OData, that users now need to know that Patient is derived from Person and use syntax such as /Person/Model.Patient to query for Patients. This seems cumbersome, and it seems to expose implementation detail to the user of the OData feed. Why should they care that Patients are derived from Persons? Users of my OData service would like to query for Patients directly.
At any rate, my question is: is it possible to have the DataService<> expose a Patients collection and a Doctors collection even though one is not generated by EF? And if so, how would be the best way to do this? I would like the Patients collection to show up in the .svc specification.
- הועבר על-ידי Larcolais Gong יום שישי 08 יולי 2011 10:42 (From:ADO.NET Entity Framework and LINQ to Entities)
כל התגובות
-
יום שישי 08 יולי 2011 10:41
I helped you moving your thread into WCF Data Services. You get more helpful suggestions there.
Best Regards,
Larcolais Gong[MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.

-
יום שישי 08 יולי 2011 14:37
Hello Larcolais,
I think this question is as much an EF question as a WCF Data Services question.
There would be no issue at all if the EF exposed a DbSet<> for Derived types. It has never sat well with me that one is forced to use the BaseClassCollection.Typeof<SubClass> syntax to query for collections of sub classes.
In my scenario, If I have a table of Doctors why can I not query them directly? Why should I have to query through the Persons object? The fact that inheritance is being used to model the data, should NOT be exposed unnecessarily. There should be a DbSet<Doctor> in the DbContext. I have never heard a compelling reason why EF has been designed this way. Can you shed any light on this?
Regards, Jonathan
-
יום חמישי 14 יולי 2011 01:07
As of today unfortunately this is not possible.
The your only real workaround is to create two ServiceOperations, one that exposes Patients and one that exposes Doctors, i.e.
[WebGet] public IQueryable<Doctor> Doctors(){ return CurrentDataSource.Persons.OfType<Doctor>(); }
These can be access and queried like this:
/Doctors()?...
/Patients()?...And it works great through the URL etc, you can compose queries / filters etc are per normal, the only problem is that Doctors() and Patients() doesn't show up in client side LINQ.
But perhaps that isn't a problem because it seems you are comfortable with Persons.OfType<Patient> and Persons.OfType<Doctor>??
Hope this helps
-Alex
- נערך על-ידי Alex D James יום חמישי 14 יולי 2011 01:08 formatting issues
- נערך על-ידי Alex D James יום חמישי 14 יולי 2011 01:08 formatting issues
-
יום חמישי 14 יולי 2011 14:05
Hi Alex, thank you for the response.
I did ended up creating [WebGet] methods, however these do not appear in the service definition, so they are less discoverable. How does someone browsing my OData service know they exist?
>>But perhaps that isn't a problem because it seems you are comfortable with Persons.OfType<Patient> and Persons.OfType<Doctor>??
Sure I'm comfortable with the syntax, but why should users of my OData service be required to know that a Doctor inherits from Person, which in turn in inherits from BusinessEntity? It's forcing them to know an inheritance hierarchy that should not need to be exposed to them unnecessarily. It is an implementation detail, and makes the service less discoverable.
Cheers,
Jonathan -
יום חמישי 14 יולי 2011 17:51
Well the first thing you need to do once you've written the [WebGet] methods is add a configuration setting to expose them:
i.e.
config.SetServiceOperationAccessRule(...)
This works in a similiar way to SetEntitySetAccessRule(...), i.e. nothing is exposed by default.If you do this the [WebGets] showup as <FunctionImports> in the $metadata endpoint.
Unfortunately our client code ignores this, but it can be discovered.Hope this helps
-Alex -
יום חמישי 14 יולי 2011 21:47
Thanks again Alex,I did add the [WebGet] method using config.SetServiceOperationAccessRule(). I have always been able to access the data, it just does not show up in the meta data.So I have:config.SetEntitySetAccessRule("WorkItems", EntitySetRights.All); config.SetEntitySetAccessRule("BusinessEntities", EntitySetRights.All); config.SetServiceOperationAccessRule("Patients", ServiceOperationRights.All);
and[WebGet] public IQueryable<Patient> Patients() { return CurrentDataSource.BusinessEntities.OfType<Patient>(); }
and I get<?xml version="1.0" encoding="utf-8"?> <service xml:base="http://localhost:6000/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://www.w3.org/2007/app"> <workspace> <atom:title>Default</atom:title> <collection href="BusinessEntities"> <atom:title>BusinessEntities</atom:title> </collection> <collection href="WorkItems"> <atom:title>WorkItems</atom:title> </collection> </workspace> </service>
Is there a separate URL to get <FunctionImports>? -
יום שישי 15 יולי 2011 08:02מנחה דיון
The service document (which is what you get when you access the root of the service) only contains the entity sets.
You would need to go to the /$metadata endpoint to get the CSDL/EDMX for the service which will contain the function imports.
Thanks,
Vitek Karas [MSFT] -
יום חמישי 03 מאי 2012 21:03
I know this is an old post, but I was curious if what's described here is still the case in the latest (beta or otherwise) versions of the Entity Framework and the WCF service.
Is there now a way to get derived types to show up in the service document and be queryable the same way the base classes are?
- נערך על-ידי moskie827 יום חמישי 03 מאי 2012 21:06