Jordan
Jordan

Reputation: 9911

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. :)

Upvotes: 1

Views: 226

Answers (2)

Ed Chapel
Ed Chapel

Reputation: 6952

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{...};
}

Upvotes: 0

mCasamento
mCasamento

Reputation: 1433

Well, if you want to go with plain WCF, you can, no problem, just change the code to

[Query(IsComposable=false)]
public IEnumerable<ProjectItemDC> GetProjectItems(string myParm1, string myParm2) 
    { 
        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 
               }.ToArray(); 
    } 

write your own filtering/sorting logic and you're done. Yes, you've lost WCF Ria Services dynamic query capabilities, but this is pretty much what you get with plain old WCF, isnt'it ?

If you instead need WCF Ria dynamic sorting/filtering/grouping you must take some additional steps, involving the visit of the Expression that WCF Ria Services create for you.

HTH

Upvotes: 1

Related Questions