Search code examples
linqentity-frameworkwcf-ria-services

Calling a query from RIA Services with entities that have children created by other methods


I have this bit of code that does not work because Entity Framework doesn't recognize the CreateItemDC method. CreateItemDC is a modular private method that creates a data contract for the given Item entity. I use CreateItemDC all throughout my service whenever I need to return an Item data contract, but I can't use it here. I can realize the sequence of ProjectItems into an array or enumerable because I would have to do this to all ProjectItem entities in my database as the query criteria is specified on the client and I don't have access to it here. Do I have any better options here? It seems that RIA Services is not worth the trouble. I'm really wishing I had used plain WCF with this project.

    [Query]
    public IQueryable<ProjectItemDC> GetProjectItems()
    {
        return from projectItem in ObjectContext.ProjectItems
               select new ProjectItemDC
               {
                   ID = projectItem.ID,
                   LibraryItem = CreateItemDC(projectItem.LibraryItem),
                   LibraryItemID = projectItem.LibraryItemID,
                   ProjectID = projectItem.ProjectID,
                   Quantity = projectItem.Quantity,
                   Width = projectItem.Width,
                   Height = projectItem.Height,
                   Depth = projectItem.Depth,
                   SheetMaterialID = projectItem.SheetMaterialID,
                   BandingMaterialID = projectItem.BandingMaterialID,
                   MaterialVolume = projectItem.MaterialVolume,
                   MaterialWeight = projectItem.MaterialWeight
               };
    }

P.S. I do love LINQ and E.F. though. :)


Solution

  • You can call ToArray() against ObjectContext.ProjectItems to force EF to load all the items, however, your query will no longer be composable on the client.

    [Query]
    public IQueryable<ProjectItemDC> GetProjectItems()
    {
        return from projectItem in ObjectContext.ProjectItems.ToArray()
               select new ProjectItemDC
               {
                   ID = projectItem.ID,
                   LibraryItem = CreateItemDC(projectItem.LibraryItem),
                   LibraryItemID = projectItem.LibraryItemID,
                   ProjectID = projectItem.ProjectID,
                   Quantity = projectItem.Quantity,
                   Width = projectItem.Width,
                   Height = projectItem.Height,
                   Depth = projectItem.Depth,
                   SheetMaterialID = projectItem.SheetMaterialID,
                   BandingMaterialID = projectItem.BandingMaterialID,
                   MaterialVolume = projectItem.MaterialVolume,
                   MaterialWeight = projectItem.MaterialWeight
               };
    }
    

    Edit:

    As mentioned in your comment, it gets all of the data out of the database at once which is not ideal. In order to create the LibraryItem with your private method, you cannot compose the query on the client. Instead, you should filter within the query method and then create the array.

    [Query]
    public IQueryable<ProjectItemDC> GetProjectItems(int id, string filter, object blah)
    {
        var projectItems = ObjectContext.ProjectItems.Where(...).ToArray();
        return projectItems.Select(projectItem => new ProjectItemDC{...};
    }