breezejs createEntity is undefined

与世无争的帅哥 提交于 2019-12-12 01:01:33

问题


Inside an AngularJS directive, I assign a new value to a scope variable:

$scope.myPerson = { TiersId: 105191, Name: "John Smith" };

Originaly the $scope.myPerson was created from a BreezeJS entity.

Assigning the new value triggers a $scope.apply() by AngularJS, which is then intercepted by BreezeJS. That's when it gets complicated.

[EDIT]

Ok, I've figured out that I need to use the EntityManager that I've registered with my dataContext:

$scope.myPerson =  myDataContext.createPerson({ TiersId: 105191, Name: "John Smith" });

  function createPerson(person) {
        return manager.createEntity("AccountOwner", person);
  }

Now, it fails in the following code:

  proto.createEntity = function (typeName, initialValues, entityState) {
    entityState = entityState || EntityState.Added;
    var entity = this.metadataStore
        ._getEntityType(typeName)
        .createEntity(initialValues);
    if (entityState !== EntityState.Detached) {
        this.attachEntity(entity, entityState);
    }
    return entity;
};

The entity type is known, but the createEntity(initialValues) function is undefined. How come ?

[EDIT]

To make things clearer, here's the relevant EF mapping as well as the model classes:

public class MandateMappings : EntityTypeConfiguration<Mandate>
{
    public MandateMappings()
    {
        Property(m => m.IBAN).HasMaxLength(34).IsFixedLength().IsUnicode(false);

        Property(m => m.AccountOwner.Name).HasMaxLength(70);  
        Property(m => m.AccountOwner.City).HasMaxLength(500); 

        Property(m => m.CreatedBy).HasMaxLength(30);
        Property(m => m.UpdatedBy).HasMaxLength(30);
    }
}



public class Mandate : Audit
{  
    public string IBAN { get; set; }

    public AccountOwner AccountOwner { get; set; }

}

public class AccountOwner
{
    public string Name { get; set; }
    public string City { get; set; }
}

public abstract class Audit
{
    public DateTime CreatedDate { get; set; }
    public string CreatedBy { get; set; }
}

回答1:


Let me clarify what I meant when I said on User Voice that Breeze supports a form of inheritance but not "database inheritance".

I meant that, today, the classes on your server-side can be part of an inheritance chain if and only if that chain is invisible to the client.

Here are some conditions consistent with that caveat:

  • Only the "terminal" class in the chain (the most derived class) maps to a database table.

  • Properties on super classes are non-public (e.g., internal) or explicitly not mapped (e.g., adorned with [System.ComponentModel.DataAnnotations.Schema.NotMapped].

  • Methods may appear on any class at any level as these are never transmitted to the client.

Here is an example of a TodoItem class that inherits from a baseClass:

public class baseClass
{
    public void DoNothing() {}
    internal string Foo { get; set; }
}
public class TodoItem :baseClass
{
    public int Id { get; set; }                   

    [Required, StringLength(maximumLength: 30)]   
    public string Description { get; set; }       

    public System.DateTime CreatedAt { get; set; }
    public bool IsDone { get; set; }              
    public bool IsArchived { get; set; }          
}

This works fine on the server. Set a breakpoint in the controller: you'll have no trouble executing DoNothing() and getting/setting the Foo property.

This works because there is no client-side consequence of this structure. The metadata are no different after deriving from baseClass than they were before. The Foo property and DoNothing methods are invisible to the client … exactly as this service author intended.

This kind of arrangement is pretty common in the real world where the many classes of a business model share functionality through a base class.

This is NOT the end of the story and it is NOT what we think people are asking for when they ask for "inheritance".

We think people want what I have been calling "database inheritance" by which I mean that two or more classes in the inheritance chain are mapped to different tables.

Breeze does not handle that today ... in part because Breeze cannot yet comprehend metadata that describe an inheritance hierarchy.

Workaround

What if you had a class hierarchy in which data properties were defined on different class levels? You can workaround the current obstacles by providing a metadata description that flattens the hierarchy from the perspective of the client.

For example, suppose you have a Person type with FirstName and LastName. And Person derives from entityBase which defines createdBy.

If you define the Person *EntityType* to have [FirstName, LastName, and createdBy] properties - essentially flattening the hierarchy - all will be well.

Flatten the hierarchy automagically

Of course that's a PITA. One approach to inheritance we could take is to do this flattening for you when you ask Breeze to generate the metadata on the server.

I'm curious: would this suffice? Or do you really NEED to know on the JavaScript client that the createdBy property belongs to a base class. If you really need to know, please tell me why.




回答2:


Edit: As of v 1.3.1 Breeze now DOES support inheritance.

Without more context I can't be sure, but I'm guessing that the issue is that Breeze does not YET have metadata about your entityType. Normally this is accomplished via your first query, but if you are creating entities before the first query then the alternative is to call the EntityManager.fetchMetadata() method instead BEFORE performing any createEntity calls. The fetchMetadata method is asynchonous, i.e. returns a promise, so you will need to perform your createEntity call inside of the 'then' portion of the promise. There are a couple of other recent 'Breeze' posts similar to this that have more details and examples.



来源:https://stackoverflow.com/questions/16103214/breezejs-createentity-is-undefined

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!