简体   繁体   中英

Is it possible to lazy load complex types from a WCF Data Service

I have DbContext subclass

ReportingContext : DbContext

As I'm doing simple CRUD I then created a WCF Data service to expose my DbSet...

public class ReportService : DataService<ReportingContext>

I have been able to use the ReportingContext directly to do 'table splitting'. Basically use 2 entities (ReportLayout and ReportLayoutData) which both use a single table. I was able to configure this using the fluent API. Everything worked fine in Unit tests as I was able to return ReportLayouts and only load ReportLayoutData when they were accessed.

My problems started when I tried to do this through a WCF Data Service, OData version 5.6 - using the DataServiceContext class. Returning ReportLayouts work fine, but trying to lazy load the dependent data has not been possible so far. I have tried different things:

  • Calling Include via a service method actually worked when I debugged the service directly and checked the generated sql - 2 separate queries as for the unit test. However, the service simply did not include the ReportLayoutData property in its returned properties when viewed in the browser and I got client side errors relating to the missing property.

     [WebGet] public IQueryable<ReportLayout> GetReportsByID(string ids) { var ints = GetInts(ids); return CurrentDataSource.Reports.Include("LayoutData").Where(x => ints.Contains(x.ReportLayoutID)).AsQueryable(); } private static int[] GetInts(string ids) { return ids.Split(",".ToCharArray()).Select(x => Convert.ToInt32(x)).ToArray(); } 
  • I tried to use DataServiceContext.Expand - $expand - and this failed with various errors as I tried slighly different arguments

  • I tried calling Execute, various problems

  • I turned the ReportLayoutData property into an IQueryable even though it is a 1-1 relationship and now it says ReportLayoutData is not a property of ReportLayout when running the EF specific unit test that previously worked fine.

My question: is it possible to Lazy Load via a WCF Data service in this manner or should I just expose 2 collections and resolve the results into a single object on the client? If it is possible I would just like to see the basic pattern - a couple of related entities, fluent API declarations and the DataService code. Thanks for any help.

EDIT

I am currently being plagued by the error:

A property with name 'LayoutData' on type 'ReportLayout' has kind 'Structural', but it is expected to be of kind 'Navigation'.

Although there is no problem retrieving the data in the browser: ReportService.svc/Reports()?$expand=LayoutData

partial stack trace:

Microsoft.Data.OData.ReaderValidationUtils.ValidateNavigationPropertyDefined(String propertyName, IEdmEntityType owningEntityType, ODataMessageReaderSettings messageReaderSettings) at Microsoft.Data.OData.Atom.ODataAtomEntryAndFeedDeserializer.TryReadNavigationLinkInEntry(IODataAtomReaderEntryState entryState, String linkRelation, String linkHRef)

I was able to remove the above error by not exposing 2 dbSets through the service. Will consider a service operation to return what I need from EF, shame it isn't so elegant.

In the end my solution was to split the table so as to create a navigation property exposed as an ICollection

I was able to implement queries such as Reports/ReportService.svc/Reports(1) $expand=LayoutData as a result (AddQueryOption("$expand", "LayoutData") and wrote a service method to do this for multiples.

    [WebGet]
    public IQueryable<ReportLayout> GetReportsByID(string ids)

I only exposed a single Dbset via the service - the children are not accessible directly.

Client side updates to the dependent entities can be achieved using the DataServiceContext methods:

AddObject, AddLink
AttachTo, UpdateObject, AttachLink //UpdateObject on the child ensures the entity state changes to modified (see DataServiceContext.Entites collection).

In retrospect I probably did not need to split the table but do not have time to play with this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM