Breeze使用EF和Web API查询本地缓存(Breeze querying local cache with EF and Web API)

编程入门 行业动态 更新时间:2024-10-25 03:23:26
Breeze使用EF和Web API查询本地缓存(Breeze querying local cache with EF and Web API)

问题

我有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.

更多推荐

本文发布于:2023-08-05 14:46:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1434080.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:缓存   Web   Breeze   EF   API

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!