Closed johnhwright closed 2 years ago
Hi @johnhwright
From version 0.80.0 to version 0.90.0 the most important change was that the resources become mutable by default, if another resource is required, that points to the same endpoint, it must be cloned. That is the function of the clone
method.
In the previous version each call to select
, expand
, filter
, etc internally generated new resources that were quickly discarded. The idea for the new version is to order and separate the handling of the path on the one hand and the querystring on the other hand.
In this way: To obtain the endpoint we move through the segments of the resources, alternating the path and generating new resources in each invocation of the methods.
var ticketsResource = this.odAdminSupportTicketService.supportTickets.clone();
var ticketResource = ticketsResource.entity(321); // Create new resource from entitySet. The new resource point to the entity
On the other hand, the queryString is mutable for each resource, this implies that I can take the same resource and alter it in its subsequent invocations.
// I initially prepare a base case of the resource
ticketsResource.query(q => {
q.filter({ or: [{ createdOn: { ge: fromDate, lt: toDate } }] });
q.select(['id', 'status', 'customer', 'messages',]);
q.expand({
customer: { select: ['email'] },
messages: { select: ['message', 'createdOn', 'createdById'] },
});
});
// Then in each successive call I can change the paging without modifying the base conditions of filtering, ordering, selection, etc.
ticketsResource.query(q => {
q.top(100);
}).fetch().subscribe();
ticketsResource.query(q => {
q.skip(100);
q.top(100);
}).fetch().subscribe();
// Or simply
ticketsResource.query(q => {
q.paging({skip:200, top: 100});
}).fetch().subscribe();
// In each call the initial select, filter and expand are preserved
I honestly liked the idea of immutability for resources but was ambiguous about how to work with them. So I opted for this new approach. The segments are immutable and create new resources. On the other hand, handling the querystring mutates the resource.
The query
method generates a context where it is possible to alter everything that corresponds to the queryString of the url.
By removing the ambiguity I can focus on improving the possibilities of that query mutation context, today it is possible to use two approaches:
// OData v4 query builder approach
ticketsResource.query(q => {
q.filter({ or: [{ createdOn: { ge: fromDate, lt: toDate } }] });
});
// OData Filter Builder approach
ticketsResource.query(q => {
q.filter(({e, s}) => e('or').ge(s.createOn, fromDate).lt(s.createOn, toDate));
});
I apologize for the relatively abrupt change, I think there are several users of the tool who were confused by the change and I hope I have helped or clarified something with this brief explanation. Greetings and thank you very much for letting me know and giving me the opportunity to try to explain the change.
New versión of the example code:
this.searchResults$ = this.odAdminSupportTicketService.supportTickets
.clone()
.query(q => {
q.filter({ or: [{ createdOn: { ge: fromDate, lt: toDate } }] });
q.select(['id', 'status', 'customer', 'messages',]);
q.expand({
customer: { select: ['email'] },
messages: { select: ['message', 'createdOn', 'createdById'] },
});
})
.get()
.pipe(...rxjs operators on data...)
this.odAdminSupportTicketService.supportTickets
not change
Oh wow. Not sure how I completely missed the part about being able to do multiple operations inside the query, assumed that the result actually have to be returned. Should have thought of that though, that's actually pretty awesome!
Great stuff, and thank you for the in depth response!
@diegomvh Just ran across a few more things to double check if you don't mind.
get
needs to be replaced with fetch
in pretty much all instances now yes?
I also use post
and patch
on the ODataEntitySetService
class. - Looks like patch
is now just modify
(or maybe update
not sure...`)?
And not sure what to do for my batch (though this one I might be able to simply work around with normal requests)?
public batch(func: (batch: ODataBatchResource) => void, options?: HttpOptions): Observable<ODataResponse<any>> {
return this.oData.batch('support-tickets').post(func, options);
}
Hi @johnhwright
Yes!, as you said, other changes are:
In the resource API, the post
, get
, put
, patch
, delete
methods are protected.
The public methods depending on the resource are:
create: call the post
method.
update: call the put
method
modify: call the patch
method
destroy: calls the delete
method
fetch: call to get
method
and for example in an entity resource:
fetchEntity: calls get
and returns only the fetched entity without the metadata
fetchModel: calls get
and returns a model for the entity and the fetched metadata
batch call were redesigned, you must pass a function that returns an observable There are two ways to interact with them:
this.odata
.batch("TripPin")
.exec(() =>
forkJoin({
airports: airports.fetch(),
people: people.fetch({ withCount: true }),
})
)
.subscribe();
let batch = this.odata.batch("TripPin")
batch.add(airports.fetch()).subscribe();
batch.add(people.fetch()).subscribe();
batch.send().subscribe();
I hope I have helped best regards
Fantastic! We've managed to get everything up to the current version and it seems to be working great!
Thank you again for the very detailed responses!
Updated to the latest version and I see that some of the syntax has changed. Are there any good examples of how existing queries should be migrated?
I'm mainly curious about
clone()
and the newquery()
function. Should you always call clone when you query, what would be the case when you wouldn't call this? How do you select and expand with the new query while filtering?We currently have uses like:
this.odAdminSupportTicketService.supportTickets
just maps tooDataServiceFactory.entitySet<ODSecureConversation>('support-tickets').entities()
in a service.So to upgrade would I'm guessing I maybe first clone, then use the new query func.
But I lose it after the query though because neither
select
norexpand
exist on theODataEntitySetResource
anymore.