1

Breeze 非常棒,但我们遇到了大型结果集的内存问题。我对自己想要实现的目标有一个想法,并且会重视有关最佳方法的任何想法......

  • 对于特殊(大)结果集,我想让 Breeze 像正常一样对服务器服务执行查询,但不将这些结果转换为实体 - 而是去掉额外的“Breeze” JSON 并给我一个 JavaScript 对象的简单列表(理想情况下,更改属性外壳以适合客户)。

  • 然后我可以将这些结果放入 ObservableArray 并使用 Knockout 绑定它们——但不会产生可观察或跟踪的每个属性的开销。

  • 当用户表示他们想要编辑记录时,我可以创建一个适当的 Breeze 实体并将其拼接到 ObservableArray 中以代替普通的 Javascript 对象。只要属性名称完全匹配,那么 Knockout 绑定就不会更明智。

  • 然后,Breeze 可以跟踪更改并像往常一样为实际编辑的少数记录提供保存。

我希望保留 Breeze 的一些价值,但避免这些大型结果集的开销。具体来说,如果可能,我想避免创建自定义(非微风)服务器端控制器方法。

任何人都可以建议闯入微风的最佳地点来尝试实现这一目标吗?(或更好的方法)

感谢您的任何评论。

4

2 回答 2

1

基本上,Breeze 只会为任何具有元数据中描述的实体类型的 json 创建“可观察对象”。当微风解析任何查询的传入结果时,它会尝试“识别”在 json 有效负载中返回的任何实体类型,如果它不能,那么它只会以原始形式返回 json 对象。此解析由“默认” JsonResultsAdapter 执行

这意味着,如果您不告诉 Breeze您的大型结果集中的“实体类型”,那么您将得到您想要的结果。Breeze 在对服务器的初始元数据调用期间获取这些实体类型“定义”。对于涉及实体框架的模型,这些类型会自动提供给模型中描述的任何类型。这意味着您创建的任何 DTO 都不会有实体类型,除非您为它们明确提供了元数据。因此,一种选择是简单地将大型结果集作为 DTO 返回。

另一个可能更好的选择是,如果这些大型结果集确实包含微风确实知道的实体类型,但您只想在特定查询中忽略它们。在这种情况下,您最好的选择是为这些根本不返回 entityType 的查询编写自定义 JsonResultsAdapter。像这样的东西:

   var customJsonResultsAdapter = new breeze.JsonResultsAdapter({
        name: "ignoreEntityTypeAdapter",

        visitNode: function (node, mappingContext, nodeContext) {
            return {  };
        }
    });

    var query = EntityQuery.from("QueryThatResultsLargeResultSet")
         .where(...)
         .using(customJsonResultsAdapter);

希望这已经足够清楚了。

于 2013-06-10T19:41:26.030 回答
0

根据上面的评论,我们在使用该customJsonResultsAdapter方法时错过了让 Breeze 连接所有导航属性等。本质上,我们想要 Breeze 的优点,而不需要将所有实体属性都变成 Knockout observables 的开销(直到我们需要它们)。

编辑:由于以前的自定义模型库方法中的错误,答案已更改为使用两个实用程序函数

作为替代解决方案,我们更改为使用内置的 Breeze backingStore modelLibrary适配器,并添加了几个函数以在需要时使单个实体Knockout 可观察。这样做的后果是:

  • 这是一种“精简”方法,非常适合只读数据。
  • Breeze拦截对这些属性的更改并像往常一样跟踪它们。
  • 我们仍然可以使用 Knockout 绑定lite实体,但是由于默认情况下属性不可观察,因此如果属性值发生更改,则网页不会更新。

当用户确实想要编辑实体时,我们会执行类似...

    function startEditing(entity, uiElement) {
        if (!breeze.utils.isObservable(entity)) {
            breeze.utils.makeObservable(entity);
            ko.applyBindings(entity, uiElement);
        }

几个重要的注意事项:

  • 我们需要applyBindings在使实体可观察之后重新进行,以便属性更改触发 Knockout 以更新 UI。
  • 我们的 makeObservable 函数使用Steve Sanderson 的 ES5 插件,因此我们的标记绑定中不需要括号(尽管仅限于 IE9+)

我在下面包含了我们的自定义函数的代码。在加载上面的 Knockout、Breeze 和 Steve 的插件后,您需要包含此代码。

// Add a function to make an individual Breeze entity observable.
// Requires the Knockout ES5 plugin from http://blog.stevensanderson.com/2013/05/20/knockout-es5-a-plugin-to-simplify-your-syntax/
// Note: Breeze must be configured to use it's built in backingStore adapter: 
//     breeze.config.initializeAdapterInstance("modelLibrary", "backingStore", true);

(function () {

    var utils = breeze.utils = breeze.utils || {};

    utils.makeObservable = function (entity) {
        var bs = entity && entity._backingStore;
        if (!bs) {
            throw new Error("Only entities provided by the backingStore adapter can be made observable");
        }
        ko.track(bs);
    };

    utils.isObservable = function (entity) {
        var result = false,
            bs = entity && entity._backingStore;
        if (bs) {
            var propNames = Object.getOwnPropertyNames(bs);
            if (propNames.length > 0) {
                result = !!ko.getObservable(bs, propNames[0]);
            }
        }
        return result;
    };

})();
于 2013-06-12T05:16:49.810 回答