Breeze很精彩,但我们遇到了大型结果集的内存问题。我知道自己想要达到的目标,并且会重视对最佳方法的任何想法......
对于特殊(大)结果集,我想让Breeze像正常一样对服务器服务执行查询但不将这些结果转换为实体 - 而是删除额外的“Breeze”JSON并给我JavaScript对象的简单列表(理想情况下,属性框更改为适合客户端)。
然后我可以将这些结果放入ObservableArray并使用Knockout绑定它们 - 但是没有可观察或跟踪的每个属性的开销。
当用户表示他们想要编辑记录时,我可以创建一个合适的Breeze实体并将其拼接到ObservableArray中代替普通的Javascript对象。只要属性名称完全匹配,那么Knockout绑定就不应该更明智了。
然后,Breeze可以跟踪更改并为实际编辑的少数记录提供正常的保存。
我希望保留Breeze的一些价值,但要避免这些大型结果集的开销。具体来说,我想尽可能避免创建自定义(非Breeze)服务器端控制器方法。
任何人都可以建议进入Breeze的最佳地点试图实现这一目标吗? (或更好的方法)
感谢您提出任何意见。
答案 0 :(得分:1)
基本上Breeze只会为任何具有元数据中描述的实体类型的json创建'observable'。当breeze解析任何查询的传入结果时,它会尝试“识别”json有效负载中返回的任何entityTypes,如果不能,那么它只返回原始形式的json对象。此解析由'default' JsonResultsAdapter 执行。
这意味着如果您不告诉Breeze 关于大型结果集中的'entityTypes',那么您将获得所需的结果。 Breeze在对服务器的初始元数据调用期间获取这些entityType'定义'。对于涉及实体框架的模型,将自动为模型中描述的任何类型提供这些类型。这意味着您创建的任何DTO都不具有entityTypes,除非您明确提供了元数据。因此,一种选择是简单地将大型结果集作为DTO返回。
另一个可能更好的选择是,如果这些大型结果集包含breeze确实知道的entityTypes,但您只想忽略它们以进行特定查询。在这种情况下,最好的选择是为这些只返回entityType的查询编写自定义JsonResultsAdapter。像这样:
var customJsonResultsAdapter = new breeze.JsonResultsAdapter({
name: "ignoreEntityTypeAdapter",
visitNode: function (node, mappingContext, nodeContext) {
return { };
}
});
var query = EntityQuery.from("QueryThatResultsLargeResultSet")
.where(...)
.using(customJsonResultsAdapter);
希望这很清楚。
答案 1 :(得分:0)
根据上面的评论,我们在使用customJsonResultsAdapter
方法时错过了Breeze连接所有导航属性等。基本上我们想要Breeze的优点,而不需要将所有实体属性设置为Knockout observable(直到我们需要它们为止)。
编辑:由于以前的自定义modelLibrary方法中的错误,答案已更改为使用两个实用程序函数
作为替代解决方案,我们更改为使用内置的Breeze backingStore
modelLibrary 适配器并添加了一些函数,以便在需要时使单个实体 Knockout observable 。其后果是:
当用户想要编辑实体时,我们会执行类似......
的操作 function startEditing(entity, uiElement) {
if (!breeze.utils.isObservable(entity)) {
breeze.utils.makeObservable(entity);
ko.applyBindings(entity, uiElement);
}
一些重要的注意事项:
applyBindings
,以便属性更改触发Knockout更新UI。我在下面列出了自定义函数的代码。在上面加载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;
};
})();