breeze: combining web api entity with 3rd party wcf service - breeze

I use Web API to return a Contrat EF Entity along with the metadata.
The Contract entity has a PersonId property which holds a foreign key to a Person entity.
That's where things get complicated.
In order to get the Person entity, I need to make a call to a WCF service. This service does not retrieve the entity using entity framekwork. In fact, the Person entity is stored in an Oracle database.
Then on the client side, I need to assign that Person entity to the Contract Entity. I suppose I need to extend the Contract model and add a property of type Person.
I have been through the Edmunds sample, which seems close to what I'm trying to do.
I don't intend to call the WCF service directly from the client. Instead I'm going to make a call to a GetPerson method in my WEB API service, which in turn will make a call to the WCF service.
So, my question is: since I've got access to the Web API service, should I try to return a IQueryable along with metadata (sounds difficult to me), or should I simply return JSON data and go the Edmunds sample's way ?
Which is going to be easier to implement ?

The Edmunds example focuses on client-side queries to HTTP services that you do not control.
In this case, it sounds like you'd prefer to have everything happen on the server that you do control ... including any side-trips to a WCF service. That would be my preference too ... although I don't know the details that are necessary to make that judgment.
If I only need the related Person when I fetch a single Contract, I think I would have my Web API action method return a Contract graph composed entirely on the server (including the Person which I fetched on the server via the WCF Service).
But you may be thinking about the client who needs many Contract entities - each expanded with related Person entities - in a single call. Is this what you mean when you ask about putting IQueryable on the method?
If so, I'd still consider composing these entirely on the server - with side-trips to get the related Person objects - and then perhaps casting the resulting collection as an IQueryable so that the client could filter. Ugh. I suspect that IQueryable isn't wise; IEnumerable is probably better. You can still pass some filtering values to the Web API method (see EntityQuery.withParameters).

Related

SAPUI5 Application Data in OData Model how to write back to backend system

I'm quite new to the Odata topic and try to understand what is the best practice scenario when working with OData service.
Sceanrio 1:
I have an complex application with several EntitySets coming from an remote Odata model, which is loaded from SAP Backend. I can read data and bind it to UI controls, thats not the problem, but what I am confused about is how I can/should write back data to the backend.
First assumption Odata is One-Way Binding:
The user manipulates inputFields , dropdowns ,tables and so on, and all data is writen to the Odata Model with createEntry() or setProperty(). Right? Or should i use another JSONModel and collect all user changes ?
Question : How do i transfer now this changes made on the Odata model to backend ? What is the best practive I have read something about batchprocessing or having an own service and trigger this one with the create() function ? Can someone just give some hints or some kind of a recipe.
Sceanrio 2:
Odata in Two-Way Binding ?
How does that work ? Which prerequisite must the backend provide in the OdataServices ? I read something that it's experimental.
YOu see I'm quite a little bit confused.
It's important to know what you will be getting if you use one-way or two-way binding. None of these binding actually involve writing data back to the back-end OData service.
In short:
One-way binding means that the model (e.g. ODataModel) only keeps your UI controls in sync. Changes made to the model, will also be cascaded to the UI controls bound to the model. However, when you change values in your UI controls, the updated value will not automatically be written back to the model.
Two-way binding means that the model keeps your UI in sync (similar to one-way binding), but on top of that, changes in your UI controls will also cascade back to the model. Two-way binding
In the one-way model, you would indeed need to programmatically update the model using createEntry and setProperty methods. Using two-way binding, this will be done automatically for you.
If you want changes to your model to be written back to your OData service on the server, you could run the 'submitChanges' method. This method will look at all changes made in the ODataModel and will send corresponding OData requests to the server to synchronise the changes with the back-end.
To make sure this is done in a consistent fashion, the ODataModel will wrap the required changes into a so-called change-set. The back-end then knows which requests belong together and will be able to roll-back all changes in a change-set whenever one of the changes fails. In ABAP you would call this a logical unit of work (LUW).
Because it may be necessary to send multiple requests to the server (e.g. if the change set change multiple entities), the ODataModel (v2) groups as many requests as possible in one batch. When this is switched on (which is the default), only one request is sent to the server instead of multiple requests, which increases performance. It would be advisable to only switch batching off for debugging purposes.
Please note that two way binding in sap.ui.model.odata.ODataModel used to be experimental, but please don't use that class anymore as it's old. Use sap.ui.model.odata.v2.ODataModel instead, as it is way better and supports lots more OData features (such as batches and two-way binding).
That's actually multiple answers in one, but I hope it clarifies some of the confusion.

Does SaveChanges violate Restful conventions?

I just finished watching John Pappa's pluralsight training video and was just blown away with how all of the pieces came together.
As I am digesting what I learned I am left with one serious after thought.
As incredibly easy breeze makes the queryable part and the CUD part of data services, the CUD part seems to have too much of a proprietary webapi method signature. It's easy to use and brilliant in how functional it is for its simplicity but we are used to Post, Put and Delete for the CUD part of things. These individual WepApi methods are more to code but they allow explicitly stated logic for saving things. I, for example, only do soft deletes, so an explicitly declared Delete webapi function would allow me to insert a deleted record in to my audit table, mark the record deleted by setting the DeletedDate and then actually not delete the record. Sometimes, based on the role of the person, you want to do overposting protections. For example CreatedDate might be a property in the entity but a client side forced/invalid change in that property should not auto-update the column on the server side. Or, while part of a ServiceTicket entity, the assigned service technician should never be able to be updated by the client unless the user has certain roles.
Where and how can these server side interventions be coded in the SaveChanges method in breeze? And what happens when people expect a fully Post/Put/Delete like "api" and breeze only provides a single method like SaveChanges?
And finally I am assuming that breeze uses the proprietary ContextProvider only because the odata implementation doesn't yet do the expand and select, right? Are there any plans to do away with that extra layer if and once wepapi odata fully implements all the odata verbs? How, if at all, has the 2012 Update 2 changed things in this regard?
Thanks

Using breeze js not to interact directly with DBContext

I'm very new with breezejs and having a few questions.
I think that breezejs has very nice features so I can replace my own datacontext. However, I don't want breezejs to interact directly with the dbcontext layer. In fact, in my application, the Service layer only exposes ViewModels - not even the real Business models - to the Controllers . So i'm not so sure whether I can use Breeze or not, since in few Breeze's examples, I only saw Breeze interact directly with DBContext.
Thanks.
=========================================
Thanks Ward for the answer,
About the features that I like from Breeze is that it will help to reduce a lot of time to build my own client-side view models. And to build a SPA, maintaining client-side view models is really painful for me, especially my application have desktop app client and other hand-held device's apps as well. Also, to handle the mapping from a JSon object to Knockout - which means with each view models, I will need a mapper as well.
Currently, my architecture is like this:
Server-side:
Repository layer <=> Service layer <=> Controllers (with the Web API that exposes to Client-side)
Controllers only can get the data (in format of a View Model) by sending request through Service.
So, my question is whether it is possible to make use of Breeze to query and also its integration with knockout.
Breeze never works directly with your DbContext; it works with the service model that you expose through endpoints on your service (e.g., Web API controller methods). But you certainly get the most value from Breeze when the client can query and save entities that are structurally the same as entities on the server.
You can retrieve ViewModels with Breeze - you can call almost any HTTP service method with Breeze. It's not clear to me how Breeze would help you manage those ViewModels on the client once you had retrieved them.
What features of Breeze seem "very nice" to you? Your answer to that question will help you determine if Breeze can be helpful with your preferred architectural style.
Querying data through Breeze without API controllers using DBContext directly should be no problem, saving might be harder but still manageable. I think the most complicated part is to get metadata to the client.
According to this SO answer, samples for exposing metadata from other sources that DBContext directly should be out in a week or so.
Meanwhile, check BreezeJS spa-template sample as there is repository pattern involved on the server side which makes it similar to your data access setup.

Dto/TransactionScripts and Odata Services

With an odata service, we can query from the clientside without using dto. Do i really need dto layer if i use odata svc? What are the cons and pros if i don't use dto. In our old system for querying mechanism there are many query service-methods that returns dto collection. But odata services confuses my mind... It seems like; the responsibility of server moves to the client. The same confusion goes on, for transaction scripts. I'm curios about your thoughts.
When you are on the server side - the only thing that matters for oData is either a EDM model or POCO models. So when you genrate a EDMX file you can always considered those to be your business object or model layer and pump then in to those namespaces. So in a way there is no business logic that you are applying in there.
But on the client side you can always centralize the oData method invocation. Since they support callbacks you can always have a view model call up a repository and pass the call back. In this way you dont bloat your view model with extensive odata query invocation. Sort of repositroy pattern is what i am talking about.
Hope this gives you a direction.
regards :)

How do you create properties on WCF Data Service objects that are dependent on the server's state?

I am trying to create a WCF Data Service that returns objects that look somewhat like my POCOs; they differ insofar as they have a single property which is computed when a query is called.
In other words say I have a POCO Film. I want to be able to query for Films which gives me Films with each with an added property 'IsAllowedToWatch'. The value of 'IsAllowedToWatch' is determined by my authentication state and the number of users currently watching that film.
I'm using Code-First EF4 and WCF Data Services. Can anyone suggest the best way of doing this?
I've solved this problem but the solution was rather convoluted. I had to employ a custom IQueryProvider that mediated between my custom business type and the database type. It all got rather ugly!

Resources