【问题标题】:Breeze manage NODB EntityTypes with DB EntityTypesBreeze 使用 DB EntityTypes 管理 NODB EntityTypes
【发布时间】:2013-05-07 07:52:24
【问题描述】:

我正在使用 Papa 的课程 CCJS 代码来研究 Breeze.js 和 SPA。使用此代码,我正在尝试管理来自服务器的附加信息,但这些信息不是来自 EntityFramework 的元数据中包含的实体。

所以我创建了一个名为 Esto 的 NO-DB 类和一个像 Lookups 这样的服务器方法:

  [HttpGet]
  public object Informacion()
    {
       var a = new Esto(....);
       var b = new Esto(.....);
       var c = new Esto(......);

    return new {a,b,c};
    }

然后在我调用的configureMetadataStore里面的model.js中:

metadataStore.addEntityType({
    shortName: "Esto",
    namespace:"CodeCamper",
    dataProperties:{
      id: {dataType: breeze.DataType.Int32,isPartOfKey: true},
      name: {dataType: breeze.DataType.String}
      }
   };

并且还在模型 entityNames 数组中定义:esto:'Esto' 作为实体

现在我在 context.js 中加载它,创建一个像 getLookups 这样的服务器端方法,但称为 getInformacion:

    function getInformacion(){
            return EntityQuery.from('Informacion')
                   .using(manager).execute()
     }

然后在成功方法中的 primeData 内部调用:

datacontext.informacion = {
    esto: getLocal('Esto',nombre)};

getLocal 在哪里:

  function getLocal(resource, ordering)
   {
        var query = EntityQuery.from(resource).orderBy(ordering);
        return manager.executeQueryLocally(query);
   }

我在 getLocal 中包含的查询中收到一个错误,指出找不到 entityTypeName: 'undefined' 或 resourceName:'Esto' 的 EntityType。

我做错了什么?

谢谢

【问题讨论】:

    标签: breeze


    【解决方案1】:

    你快到了! :-) 如果您在查询中指定了目标EntityType,我认为它会起作用。

    试试这个:

    var query = EntityQuery.from(resource).orderBy(ordering).toType('Esto');

    toType() 方法告诉 Breeze,此查询返回的顶级对象将是 Esto 类型。

    为什么?

    让我们考虑一下 Breeze 如何解释查询规范。

    请注意,您开始查询时,正如我们通常所做的那样,通过命名将提供数据的资源。此资源通常是到远程服务端点的路径段,可能是 Web API 控制器方法的名称……一个名为“Foos”的方法。

    了解查询资源名称很少与EntityType 名称相同!它们可能相似 - “Foos”(复数)类似于类型名称“Foo” (单数)。但资源名称可能是别的东西。它可能是“GetFoos”或“GreatFoos”或任何东西。重要的是服务方法返回“Foo”实体。

    Breeze 需要一种将 resource 名称与 EntityType 名称相关联的方法。 Breeze 本身并不知道相关性。 toType() 方法是告诉 Breeze 的一种方式。

    为什么没有toType() 远程查询可以工作?

    您通常不会在查询中添加toType()。为什么是现在?

    大多数时候 [1],Breeze 不需要知道EntityType 直到数据从服务器到达。当 JSON 查询结果包含类型名称时(例如,当它们来自 Breeze Web API 控制器时),Breeze 可以在没有我们帮助的情况下将到达的 JSON 数据映射到实体中……假设这些类型名称在元数据中。

    本地缓存查询不同

    当您查询缓存时...比如说executeQueryLocally...Breeze 必须知道要搜索哪个缓存的实体集才能在本地查询

    它“知道”你是否用toType() 指定类型。但是,如果您省略 toType(),Breeze 将不得不使用查询的资源名称。

    Breeze 不会猜。相反,它会在 EntityType/ResourceName 映射中查找与查询资源名称匹配的实体集。

    资源名称指的是服务端点,而不是缓存的实体集。例如,没有名为“Informacion”的实体集。因此 Breeze 使用 EntityType/ResourceName 映射来查找与查询资源名称关联的实体类型。

    实体类型/资源名称

    EntityType/ResourceName 映射是 Breeze MetadataStore 中的项目之一。你可能从未听说过它。那挺好的;你不应该考虑它......除非你做一些不寻常的事情,比如定义你自己的类型。

    MetadataStore 的地图一开始是空的。如果这些元数据包含 EntityType/Resource 映射,Breeze 会从服务器元数据中填充它。

    例如,Breeze EFContextProvider 使用从 DbSet 名称派生的映射生成元数据。当您定义Foo 类并将其从DbContext 公开为名为“Foos”的DbSet 时,EFContextProvider 元数据生成器添加从“Foos”资源名称到Foo 实体类型的映射。

    控制器开发人员倾向于使用DbSet 名称作为方法名称。传统的 Breeze Web API 控制器“Foo”查询方法如下所示:

    [得到] 公共 IQueryable Foos() {...}

    现在,如果您进行这样的查询:

    var query = EntityQuery.from('Foos').where(...);

    并将其应用于缓存

    manager.query.executeLocally(query).then(...);

    它只是工作。

    为什么?因为

    • “Foos”是服务器上DbSet 的名称
    • EFContextProvider 生成的元数据映射 ["Foos" 到 Model.Foo]
    • Web API 控制器提供Foos 操作方法。
    • BreezeJS query 指定“Foos”
    • executeLocally 方法在元数据中查找 ["Foos"-to-Model.Foo] 映射,并将查询应用于Foo 的实体集。

    端到端约定对您有利。

    ...直到您提到不在 EntityType/ResourceName 映射中的资源名称!

    注册资源名称

    没问题!

    您可以添加自己的资源到实体类型的映射,如下所示:

    var metadataStore = manager.metadataStore; var typeName = '一些类型名称'; var entityType = metadataStore.getEntityType(typeName); metadataStore.setEntityTypeForResourceName(resource, entityType);

    Breeze 也对类型的名称感到满意:

    metadataStore.setEntityTypeForResourceName(resource, typeName);

    在您的情况下,在您的 DataContext 顶部附近的某处,您可以写:

    var metadataStore = manager.metadataStore; // 将两个资源名称映射到 Esto metadataStore.setEntityTypeForResourceName('Esto', 'Esto'); metadataStore.setEntityTypeForResourceName('Informacion', 'Esto');

    不要过度使用toType()

    当您需要将查询结果中的顶级对象映射到EntityType 时,toType() 方法是一个很好的捷径解决方案。您不必为注册资源名称而烦恼。

    但是,您必须记住将toType() 添加到每个需要它的查询中。使用资源到实体类型的映射配置 Breeze 元数据,您每次都会获得所需的行为。

    注意事项

    [1]“大多数情况下,Breeze 在数据从服务器到达之前不需要知道EntityType”一个重要的例外 - 超出了本次讨论的范围- 当查询过滤器涉及日期/时间时。

    【讨论】:

    • 谢谢,这真的有助于我了解 Breeze 的真正工作原理
    【解决方案2】:

    我认为这里的问题是您假设实体类型名称和资源名称是同一件事。资源名称是用于执行查询的名称

    var q = EntityQuery.from(resourceName);
    

    在您的情况下,“resourceName”是“Informacion”,而 entityType 实际上是“Esto”。 Breeze 能够在远程查询上建立这种连接,因为它可以检查作为查询“Informacion”的结果从服务器返回的结果,并看到它们实际上是“Esto”实例。这对于本地查询是不可能的,因为 Breeze 不知道从哪个本地集合开始。

    在这种情况下,您需要通过 MetadataStore.setEntityTypeForResourceName 方法为 Breeze 提供更多信息。像这样的:

    var estoType = manager.metadataStore.getEntityType("Esto");
    manager.metadataStore.setEntityTypeForResourceName("Informacion", estoType);
    

    请注意,如果资源是通过实体框架元数据定义的,则这实际上不是必需的,因为 Breeze 会自动将所有 EF EntitySet 名称与资源名称相关联,但此信息不适用于 DTO。

    另请注意,单个实体类型可以拥有任意数量的资源名称。只需确保在尝试本地查询之前注册资源名称。

    【讨论】:

    • 感谢杰伊的回答。与 Breeze 合作愉快
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-20
    • 1970-01-01
    • 1970-01-01
    • 2013-06-03
    • 2021-11-26
    • 2021-12-31
    相关资源
    最近更新 更多