Search code examples
javascriptangularjsentity-frameworkodatabreeze

Breeze js AutoGeneratedKeyType is always 'none' with ODataConventionModelBuilder


I have a simple entityframework poco object

public partial class Location: Entity
{
    [Key]
    public int Id { get; set; }
    public string Description { get; set; }
}

The baseClass Entity looks as follow

public abstract class Entity : IObjectState
{
    [NotMapped]
    public ObjectState ObjectState { get; set; }
}

I expose this object via a Odata service using the ODataConventionModelBuilder

        var server = GlobalConfiguration.DefaultServer;
        ODataModelBuilder builder = new ODataConventionModelBuilder();
        builder.Namespace = "MyNameSpace.Models";
        builder.EntitySet<Location>(typeof(Location).Name);
        var model = builder.GetEdmModel();
        config.Routes.MapODataServiceRoute("odata", "odata", model, new DefaultODataBatchHandler(server));


        config.AddODataQueryFilter();

When i consume this service with Breeze js i get an error from breeze when i try to create an entity with manager.CreateEntity().

Cannot attach an object to an EntityManager without first setting its key or setting its entityType 'AutoGeneratedKeyType' property to something other than 'None'

When i query an entity and edit the data and save it. All is ok.

I am using angular in combination with breeze on the client and Asp.net webapi 2 in combination with an odatacontroller on the server with EntityFramework 6 as ORM.

Can someone tell me what i am doing wrong!!!


Solution

  • Microsoft's ODataConventionModelBuilder is very incomplete, and they are aware of it ( This applies to both OData WebApi v 2.1 and v 2.2). Along with a number of smaller issues, it does not support 'referentialConstraints' or any info on store generated keys. MS is aware of these issues, among others, and has said that some of them will be fixed in a new release sometime in October.

    Until then you have a couple of options.

    • Use the ODataConventionBuilder but then update breeze's metadataStore after the metadata is fetched to 'fix' the missing or wrong metadata.

      myMetadataStore.metadataFetched.subscribe(function(args) {
        var ms = args.metadataStore;
        var entityType = ms.getEntityType("Customer");
        entityType.setProperties({ autoGeneratedKeyType: AutoGeneratedKeyType.Identity });
        dp = entityType.getDataProperty("companyName");
        dp.validators.push(Validator.maxLength({ maxLength: 40 }));
        // etc... 
      });
      
    • Avoid fetching metadata from the server at all and just describe the metadata on the breeze client directly: (see: http://www.breezejs.com/documentation/metadata-by-hand)

    • Skip OData completely and use the Breeze WebApi implementation (see http://www.breezejs.com/documentation/aspnet-web-api). This has the advantage of being both the most complete and the most robust implementation of all of breeze's features. Most of the Entity Framework samples in breeze.js.samples are built with this.

    In general, we REALLY recommend the last choice if it is available to you. Please read this (http://www.breezejs.com/documentation/odata-server) for more information.