问题
我有6个下降的视图。 其中每个都由Web API调用填充。 我想使用breeze从远程服务器填充后在本地运行查询
当数据调用针对服务器时,代码运行正常。 问题是尝试查询本地缓存时。 我从来没有得到任何结果。 我的方法有缺陷还是我做错了什么?
服务器端
查看模型
class genericDropDown() { public int value{get;set;} public string option{get;set;} }WebAPI [单一样本方法]
[HttpGet] // GET api/<controller> public object GetSomeVals() { return _context.getClinician(); }存储库[单一样本方法]
public IEnumerable<genericDropDown> getDropDownVal() { return context.somemodel(a=>new{a.id,a.firstname,a.lastname}).ToList(). Select(x => new GenericDropDown { value = x.id, option = x.firstname+ " " + x.lastname});} }客户端
Datacontext.js
var _manager = new breeze.EntityManager("EndPoint"); //Being called from my view model var getDropDownBindings = function(KO1, KO2) { //First add the entity to the local metadatastore then populate the entity $.when( addDD('clinicianDropDown', webAPIMethod), getData(KO1, webAPIMethod, null, 'clinicianDropDown'), addDD('docTypeDropDown', webAPIMethod); getData(KO2, webAPIMethod, null, 'docTypeDropDown'), ).then(querySucceeded).fail(queryFailed); function querySucceeded(data) { logger.log('Got drop down vals', "", 'dataContext', true); } }; //Add the entity to local store. First param is typename and second is resource name (Web API method) var addDD = function(shortName,resName) { _manager.metadataStore.addEntityType({ shortName: shortName, namespace: "Namespace", autoGeneratedKeyType: breeze.AutoGeneratedKeyType.Identity, defaultResourceName:resName, dataProperties: { value: { dataType: DataType.Int32, isNullable: false, isPartOfKey: true }, option: { dataType: DataType.String, isNullable: false } } }); return _manager.metadataStore.registerEntityTypeCtor(shortName, null, null); }; //Get the data var getData = function(observableArray, dataEndPoint, parameters, mapto) { if (observableArray != null) observableArray([]); //TO DO: Incorporate logic for server or local call depending on // whether this method is accessed for the first time var query = breeze.EntityQuery.from(dataEndPoint); if (mapto != null && mapto != "") query = query.toType(mapto); if (parameters != null) query = query.withParameters(parameters); //This approach doesnt work on local querying as Jquery complains //there is no 'then' method. Not sure how to implement promises //when querying locally /* return _manager.executeQuery(query).then(querySucceeded).fail(queryFailed); function querySucceeded(data) { if (observableArray != null) observableArray(data.results); } */ //The array length from this query is always 0 var data = _manager.executeQueryLocally(query); observableArray(data.results); return; }; //Generic error handler function queryFailed(error) { logger.log(error.message, null, 'dataContext', true); }viewmodel.js
//In Durandal's activate method populate the observable arrays dataContext.getDropDownBindings (KO1,KO2);Viewmodel.html
<select class="dropdown" data-bind="options: KO1, optionsText: 'option', value: 'value', optionsCaption: 'Clinicians'"></select> <select class="dropdown" data-bind="options: KO2 optionsText: 'option', value: 'value', optionsCaption: 'Document Types'"></select>Problem
I have a view with 6 drop downs. Each of which is being populated by a Web API call. I want to use breeze to run the query locally once it has populated from the remote server
The code runs fine when the data call is against the server. The issue is when trying to query the local cache. I never get any results returned. Is my approach flawed or am I doing something wrong ?
SERVER SIDE
View model
class genericDropDown() { public int value{get;set;} public string option{get;set;} }The WebAPI [A single sample method]
[HttpGet] // GET api/<controller> public object GetSomeVals() { return _context.getClinician(); }The Repository [A single sample method]
public IEnumerable<genericDropDown> getDropDownVal() { return context.somemodel(a=>new{a.id,a.firstname,a.lastname}).ToList(). Select(x => new GenericDropDown { value = x.id, option = x.firstname+ " " + x.lastname});} }CLIENT SIDE
Datacontext.js
var _manager = new breeze.EntityManager("EndPoint"); //Being called from my view model var getDropDownBindings = function(KO1, KO2) { //First add the entity to the local metadatastore then populate the entity $.when( addDD('clinicianDropDown', webAPIMethod), getData(KO1, webAPIMethod, null, 'clinicianDropDown'), addDD('docTypeDropDown', webAPIMethod); getData(KO2, webAPIMethod, null, 'docTypeDropDown'), ).then(querySucceeded).fail(queryFailed); function querySucceeded(data) { logger.log('Got drop down vals', "", 'dataContext', true); } }; //Add the entity to local store. First param is typename and second is resource name (Web API method) var addDD = function(shortName,resName) { _manager.metadataStore.addEntityType({ shortName: shortName, namespace: "Namespace", autoGeneratedKeyType: breeze.AutoGeneratedKeyType.Identity, defaultResourceName:resName, dataProperties: { value: { dataType: DataType.Int32, isNullable: false, isPartOfKey: true }, option: { dataType: DataType.String, isNullable: false } } }); return _manager.metadataStore.registerEntityTypeCtor(shortName, null, null); }; //Get the data var getData = function(observableArray, dataEndPoint, parameters, mapto) { if (observableArray != null) observableArray([]); //TO DO: Incorporate logic for server or local call depending on // whether this method is accessed for the first time var query = breeze.EntityQuery.from(dataEndPoint); if (mapto != null && mapto != "") query = query.toType(mapto); if (parameters != null) query = query.withParameters(parameters); //This approach doesnt work on local querying as Jquery complains //there is no 'then' method. Not sure how to implement promises //when querying locally /* return _manager.executeQuery(query).then(querySucceeded).fail(queryFailed); function querySucceeded(data) { if (observableArray != null) observableArray(data.results); } */ //The array length from this query is always 0 var data = _manager.executeQueryLocally(query); observableArray(data.results); return; }; //Generic error handler function queryFailed(error) { logger.log(error.message, null, 'dataContext', true); }viewmodel.js
//In Durandal's activate method populate the observable arrays dataContext.getDropDownBindings (KO1,KO2);Viewmodel.html
<select class="dropdown" data-bind="options: KO1, optionsText: 'option', value: 'value', optionsCaption: 'Clinicians'"></select> <select class="dropdown" data-bind="options: KO2 optionsText: 'option', value: 'value', optionsCaption: 'Document Types'"></select>最满意答案
您只能对元数据描述的类型执行本地查询。
没有更多的信息,我无法确定,但我的猜测是你的GetSomeVals方法不返回'实体'而只是松散的数据。 换句话说,从GetSomeVals方法返回的对象类型必须是实体(或包含投影中的实体),以便breeze能够执行本地查询。 这是因为Breeze知道如何缓存和查询实体,但不知道如何缓存“任意”查询结果。
请注意,您可以从服务器返回包含不同类型实体的匿名类型(为了填充大多数静态小数据集),但各个项必须是“实体”。 在这种情况下,Breeze将拆分匿名结果并挑选出包含在EntityManager缓存中的任何实体。
根据您如何使用promises执行本地查询的问题,请使用带有using方法的FetchStrategy.FromLocalCache 。
即这个查询
var results = em.executeQueryLocally(query)也可以表示为:
query = query.using(FetchStrategy.FromLocalCache); return em.executeQuery(query).then(data) { var results = data.results; }本地查询仍然同步执行,但看起来是异步的。
You can only execute local queries against types that are described by metadata.
Without more information I can't be sure, but my guess is that your GetSomeVals method is not returning 'entities' but just loose data. In other words, the types of objects returned from the GetSomeVals method must be entities (or contain entities within a projection) in order for breeze to be able to perform a local query. This is because Breeze knows how to cache and query entities but has no ideas how to cache 'arbitrary' query results.
Note that you can return an anonymous type containing entities of different types from the server, (in order to populate mostly static small datasets), but the individual items must be 'entities'. In this case, Breeze will take apart the anon result and pick out any entities to include in the EntityManager cache.
Per you question of how to perform an local query with promises, use the FetchStrategy.FromLocalCache with the using method.
i.e. this query
var results = em.executeQueryLocally(query)can also be expressed as:
query = query.using(FetchStrategy.FromLocalCache); return em.executeQuery(query).then(data) { var results = data.results; }The local query is still executed synchonously but is made to look async.
更多推荐
发布评论