0

在 AngularJS 指令中,我为范围变量分配了一个新值:

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

最初 $scope.myPerson 是从 BreezeJS 实体创建的。

分配新值会触发 AngularJS 的 $scope.apply(),然后被 BreezeJS 拦截。那是它变得复杂的时候。

[编辑]

好的,我发现我需要使用我在 dataContext 中注册的 EntityManager:

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

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

现在,它在以下代码中失败:

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

实体类型是已知的,但 createEntity(initialValues) 函数未定义。怎么来的 ?

[编辑]

为了让事情更清楚,这里是相关的 EF 映射以及模型类:

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; }
}
4

2 回答 2

1

编辑:从 v 1.3.1 起,Breeze 现在支持继承。

如果没有更多上下文,我无法确定,但我猜问题是 Breeze 还没有关于您的 entityType 的元数据。通常这是通过您的第一个查询完成的,但如果您在第一个查询之前创建实体,那么替代方法是在执行任何 createEntity 调用之前调用EntityManager.fetchMetadata()方法。fetchMetadata方法是异步的,即返回一个promise,因此您需要在promise 的'then' 部分内执行createEntity 调用最近还有其他一些与此类似的“微风”帖子,其中包含更多详细信息和示例。

于 2013-04-19T17:31:53.563 回答
1

让我澄清一下我在 User Voice上说 Breeze 支持一种继承形式但不支持“数据库继承”时的意思。

我的意思是,今天,当且仅当该链对客户端不可见时,服务器端的类才能成为继承链的一部分。

以下是与该警告一致的一些条件:

  • 只有链中的“终端”类(最派生类)映射到数据库表。

  • 超类的属性是非公开的(例如,内部的)或显式未映射的(例如,用[System.ComponentModel.DataAnnotations.Schema.NotMapped].

  • 方法可能出现在任何级别的任何类中,因为它们永远不会传输给客户端。

下面是一个TodoItem继承自 a 的类的示例baseClass

公共类基类
{
    公共无效 DoNothing() {}
    内部字符串 Foo { get; 放; }
}
公共类 TodoItem :baseClass
{
    公共 int ID { 获取;放; }                   

    [必需,字符串长度(最大长度:30)]   
    公共字符串描述 { 获取;放; }       

    公共 System.DateTime CreatedAt { get; 放; }
    公共布尔 IsDone { 得到;放; }              
    公共布尔 IsArchived { 获取;放; }          
}

这在服务器上工作正常。在控制器中设置断点:执行DoNothing()和获取/设置Foo属性将毫无问题。

这是可行的,因为这种结构没有客户端结果。派生后的元数据与baseClass以前没有什么不同。Foo属性和DoNothing方法对客户端是不可见的……完全符合此服务作者的意图。

这种安排在现实世界中非常常见,其中业务模型的许多类通过基类共享功能。

这不是故事的结局,也不是​​我们认为人们要求“继承”时所要求的。

我们认为人们想要我所说的“数据库继承”,我的意思是继承链中的两个或多个类映射到不同的表。

Breeze 今天还没有处理这个问题……部分原因是 Breeze 还不能理解描述继承层次结构的元数据。

解决方法

如果您有一个类层次结构,其中数据属性定义在不同的类级别上怎么办?您可以通过提供从客户端的角度扁平化层次结构的元数据描述来解决当前的障碍。

例如,假设您有一个Person带有FirstNameand的类型LastName。并Person派生自entityBase其中定义createdBy

如果您将Person *EntityType* 定义为具有 [ FirstNameLastNamecreatedBy] 属性 - 本质上是扁平化层次结构 - 一切都会好起来的。

自动展平层次结构

当然,这是一个 PITA。我们可以采用的一种继承方法是,当您要求 Breeze 在服务器上生成元数据时,为您执行此扁平化。

我很好奇:这就够了吗?或者您真的需要在 JavaScript 客户端上知道该createdBy属性属于基类。如果你真的需要知道,请告诉我为什么。

于 2013-04-20T22:36:06.870 回答