1
votes

We are using Breeze for the first time in a real world application and it is a fantastic framework. We are experiencing issues with inheritance in that when querying for an entity with a polymorphic navigation collection, we can see the data returned of derived types in JSON but then the collection is not populated in the Breeze entities on the client. We have C# classes on the server which Entity Framework persists to the database using the Table-Per-Type strategy. There is a base abstract class called Client and SpecialClient inherits from it:

    public abstract class Client
    {
        public int Id { get; set; }
        public int QuoteID { get; set; } //Foreign Key for navigation

        public string FirstName { get; set; }
        public string FamilyName { get; set; }
    }

    public class SpecialClient : Client
    {
        public decimal Income { get; set; }
        public string ClientType { get; set; }
    }

Then we have a parent class called Quote, with a collection navigation property of the base Client:

public class Quote
{
    public Quote()
    {
        Clients = new List<Client>();
    }

    public int Id { get; set; }
    public string Reference { get; set; }           
    public string Comments { get; set; }
    public DateTime EffectiveDate { get; set; }

    public List<Client> Clients { get; set; }
}

(We have moved the primary/foreign key properties to partial classes but shown them in the same classes here for brevity, not sure if partials would cause an issue?)

We then tried a client-side Breeze query to retrieve a Quote and expand the Clients property (we have a Web API Breeze Controller with a normal Quotes Action using a repository that holds the EF context and Breeze ContextProvider):

    [HttpGet]
    public IQueryable<Quote> Quotes()
    {
        return _repository.Quotes();
    }

and a Breeze query:

var query = breeze.EntityQuery.from('Quotes').expand('Clients');

When looking at the entities returned we have a Quote entity but the Clients array has not been populated with any Client entities. We have checked the metadata and it seems to look good, it knows about the base types and derived types and we have checked that we have a foreign key mapped between Quote and Client which is also reflected in the metadata. We also checked the JSON resulting from the query, and again, everything looks good, the Clients navigation collection is populated on the Quote entity. It appears Breeze just will not populate the entities when the query returns with the data.

We tried removing the SpecialClient class inheriting from Client, and this then worked in that we got a collection populated of the base client entities, so it does seem connected to the inheritance. We also tried to see if we could query the derived SpecialClient but we cannot seem to work out how to query derived types in a navigation property that specifies the base type with a predicate:

var pred = new breeze.Predicate("Clients", "any", "clientType", "==", 'Life1'));

We are not sure how to specify that we want to query on the SpecialClient derived type. When we tried the above, Breeze complains that Client does not have a clientType property.

Much appreciated if anyone could advise on how to handle this type of inheritance querying and expanding issue and where we are going wrong or if this is a bug (the not expanding part). We are using Web API 2 (5.0.1), Breeze (with EF6 context Provider) 1.4.11 and we have checked that all of our client and server packages are all 1.4.11.

How can we instruct Breeze that we have derived types in Navigation collections and we want to query and retrieve them?

Many Thanks for help!

EDIT 1: Should also mention that we are not using any special EF mapping other than basic convention.

2

2 Answers

2
votes

By looking at the DocCode sample we seem to have resolved this issue. It turns out that we did not have a reference navigation from the base class Client back to the principle class Quote which holds the navigation collection of base Clients:

public abstract class Client
{
    public int Id { get; set; }
    public int QuoteId { get; set; } //Foreign Key for navigation

    public string FirstName { get; set; }
    public string FamilyName { get; set; }

    public Quote quote { get; set; }    //Added this nav property back to Quote principle!
}

Although we had a QuoteId property for the foreign key to the principle, it looks like we also needed a reference back to Quote from the base Client class. We now can query with expand and the Clients collection is filled with derived types. Is this the correct way of implementing this type of modeling in Breeze? Also, would it be an idea to add a section to the Breeze website docs on inheritance, or would that be too specific to particular backend ORM choices?

On an associated note, is it possible to do query restrictions (wheres or predicates) with properties on the derived types? We got round this by pushing the query to our server repository and doing a LINQ Where with OfType() to get properties we wanted to restrict on, and we were wondering if Breeze can do this in the client (we couldn't see anything clear in the docs).

Thanks for your help, and keep up the fantastic work with Breeze, we are loving the framework!

0
votes

I haven't looked at this in detail yet but in our DocCode sample we have a similar relationship between Customers and Orders/InternationalOrders, where the Customer.Orders property can return either Orders or InternationalOrders. Take a look a that sample and see how it differs from yours.