Context: Repository-pattern, WCF, WPF/SL
In my Repository of self-tracking Entities i need to explicitly load some related properties in order to correctly process the query. Those are not the includes requested by the client and i would like to get rid of them in order to keep network traffic resonable. My solution so far is this:
Receive Query
Load includes necessary to answer request
Execute Query
Create temporary IEnumerable
Iterate 4) and load all items again, this time with the include-path requested from the client-app only
return entities via WCF
I would like to do this:
Receive Query
Load all includes (infrastructure plus client-requested)
Execute Query
Unload "Infrastructure" includes
return entities via WCF
What is the proper way to do this?
Thanks,
Armin
How about lazy loading and proper DTO response objects ?
WCF returns custom Order or GetOrderResponse (Contracts.Order)
Load Order from EntityModel through repository (just the order)
Use automapper for mapping EntityModel.Order => Contracts.Order
Result : only the corresponding properties inside Contracts.Order are loaded:
Ex. Contracts.Order
Number
OrderDetails (=> Only this property is loaded through lazy loading because it is mapped)
If you are building a SOA or webservice, don't let the client specify load graphs. If it's necessary for the client to specify load graphs consider deploying the Model using WCF Data Services, works great.
Perhaps you could build two systems .. one SOA and one (readonly) Data Service.
Related
Here is my situation. I use Entity Framework 4 with the Web API
The structure of my code is quite simple, I have the Service layer where all my rest API is organized, I have my Business logic layer where I have business controllers to manage Transactions between the rest calls and the data layer. Finally, I have a data layer with generic repositories and a DAO to access the whole thing.
In my Business controllers, I use using to inject a non transactionnal (read only methods) OR a transactional (CRUD methods) DbContext.
When returning values to my REST API, I parse it into JSON.
The problem is that I keep having this exception: Newtonsoft.Json.JsonSerializationException
I return my entities / collections / lists outside of my using{} statement, which I think EF does not like by default.
In debug mode, sometimes, I will manage to retrieve all data, but not all the time. Since my entities come from a query within a DbContext, I think that the behavior is to remove loaded sub-properties after the context has been disposed of.
Fact is, I want to keep my structure as is, and I was wondering the following:
Is there a way of returning complete (not lazy-loaded) entities after leaving the using{} statement?
Thanks a lot
I actually read more about Entity Frameworks behavior. What I get is actually standard for EF. I have to force the context to Load() my refered entities in order to get them after leaving the context.
I am trying to setup an OData service using WCF Data Services with Entity Framework 6.
I created my service by inheriting from EntityFrameworkDataService which works fine for retrieving all data. I would like to add a security layer on top of my entities so that not all tables / fields are visible over the OData service.
I have tried the QueryInterceptors which work ok as far as limiting the table. It is not possible to return a limited entity (removing properties user does not have access to). The admin will decide which use has access to table and fields therefore I can not pre-create sub entities. There will be over 100 tables in the database so the solution needs to be generic.
I have also looked at WCF Data Services ability to restrict returned fields. However since I do not have DataMember / DataContract etc on my entities also no place to expose OperationContract either, this solution also does not fit.
I am developing a SPA using Angular-Breeze-WebAPI-EntityFramework.
Now Breeze uses the Entity Framework metadata information to create it's own Breeze models. We use this in our application for Breeze validation.
So far, it's all been nice and easy. Now we are having to create a search page (say for querying customers). The search can be by Customer.Name or by Product.Id (which would return a list of customers who have bought that product). The result is a ng-repeater, which displays Customer.Name, Order.LastPlaced etc.
if you are getting confused by the tables and columns, forget that. What I am only trying to get to is that, both the search object and the result object are not 1:1 with Entity tables (or objects). So obviously I feel the need to create a custom object (one for the search and one for the results). My question primarily is where and how do I create that object?
If I create it at the data layer, Breeze would have no idea of the metadata for each of the properties (since it uses EF for that).
I obviously can't create just a JavaScript object, since I will have to query the database (using EF) to search and populate the object.
So where does one create such a custom object (traversing multiple tables) such that Breeze still can figure out the metadata and perform validation and such when the need arises?
Thank you all.
You can create metadata on the client for types that the server either doesn't know about or doesn't have the schema for. See http://www.breezejs.com/documentation/metadata-by-hand.
we have a huge database application, which must get refactored (there are so many reasons for this. biggest one: security).
What we already have:
MySQL Database
JPA2 (Eclipselink) classes for over 100 tables
Client application that accesses the database directly
What needs to be there:
REST interface
Login/Logout with roles via database
What I've done so far:
Set up Spring MVC 3.2.1 with Spring Security 3.1.1
Using a custom UserDetailsService (contains just static data for testing atm)
Created a few Controllers for testing (simply receiving/providing data)
Design Problems:
We have maaaaany #OneToMany and #ManyToMany relations in our database
1.: (important)
If I'd send the whole object tree with all child objects as a response, I could probably send the whole database at once.
So I need a way to request for example 'all Articles'. But it should omit all the child objects. I've tried this yesterday and the objects I received were tons of megabytes:
#PersistenceContext
private EntityManager em;
#RequestMapping(method=RequestMethod.GET)
public #ResponseBody List<Article> index() {
List<Article> a = em.createQuery("SELECT a FROM Article a", Article.class).getResultList();
return a;
}
2.: (important)
If the client receives an Article, at the moment we can simply call article.getAuthor() and JPA will do a SELECT a FROM Author a JOIN Article ar WHERE ar.author_id = ?.
With REST we could make a request to /authors/{id}. But: This way we can't use our old JPA models on the client side, because the model contains Author author and not Long author_id.
Do we have to rewrite every model or is there a simpler approach?
3.: (less important)
Authentication: Make it stateless or not? I've never worked with stateless auth so far, but Spring seems to have some kind of support for it. When I look at some sample implementations on the web I have security concerns: With every request they send username and password. This can't be the right way.
If someone knows a nice solution for that, please tell me. Else I'd just go with standard HTTP Sessions.
4.:
What's the best way to design the client side model?
public class Book {
int id;
List<Author> authors; //option1
List<Integer> authorIds; //option2
Map<Integer, Author> idAuthorMap; //option3
}
(This is a Book which has multiple authors). All three options have different pros and cons:
I could directly access the corresponding Author model, but if I request a Book model via REST, I maybe don't want the model now, but later. So option 2 would be better:
I could request a Book model directly via REST. And use the authorIds to afterwards fetch the corresponding author(s). But now I can't simply use myBook.getAuthors().
This is a mixture of 1. and 2.: If I just request the Books with only the Author ids included, I could do something like: idAuthorMap.put(authorId, null).
But maybe there's a Java library that handles all the stuff for me?!
That's it for now. Thank you guys :)
The maybe solution(s):
Problem: Select only the data I need. This means more or less to ignore every #ManyToMany, #OneToMany, #ManyToOne relations.
Solution: Use #JsonIgnore and/or #JsonIgnoreProperties.
Problem: Every ignored relation should get fetched easily without modifying the data model.
Solution: Example models:
class Book {
int bId;
Author author; // has #ManyToOne
}
class Author {
int aId;
List<Book> books; // has #OneToMany
}
Now I can fetch a book via REST: GET /books/4 and the result will look like that ('cause I ignore all relations via #JsonIgnore): {"bId":4}
Then I have to create another route to receive the related author: GET /books/4/author. Will return: {"aId":6}.
Backwards: GET /authors/6/books -> [{"bId":4},{"bId":42}].
There will be a route for every #ManyToMany, #OneToMany, #ManyToOne, but nothing more. So this will not exist: GET /authors/6/books/42. The client should use GET /books/42.
First, you will want to control how the JPA layer handles your relationships. What I mean is using Lazy Loading vs. Eager loading. This can easily be controller via the "fetch" option on the annotation like thus:
#OneToMany(fetch=FetchType.Lazy)
What this tells JPA is that, for this related object, only load it when some code requests it. Behind the scenes, what is happening is that a dynamic "proxy" object is being made/created. When you try to access this proxy, it's smart enough to go out and do another SQL to gather that needed bit. In the case of Collection, its even smart enough to grab the underlying objects in batches are you iterate over the items in the Collection. But, be warned: access to these proxies has to happen all within the same general Session. The underlying ORM framework (don't know how Eclipselink works...I am a Hybernate user) will not know how to associate the sub-requests with the proper domain object. This has a bigger effect when you use transportation frameworks like Flex BlazeDS, which tries to marshal objects using bytecode instead of the interface, and usually gets tripped up when it sees these proxy objects.
You may also want to set your cascade policy, which can be done via the "cascade" option like
#OneToMany(cascade=CascadeType.ALL)
Or you can give it a list like:
#OneToMany(cascade={CascadeType.MERGE, CascadeType.REMOVE})
Once you control what is getting pulled from your database, then you need to look at how you are marshalling your domain objects. Are you sending this via JSON, XML, a mixture depending on the request? What frameworks are you using (Jackson, FlexJSON, XStream, something else)? The problem is, even if you set the fetch type to Lazy, these frameworks will still go after the related objects, thus negating all the work you did telling it to lazily load. This is where things get more specific to the mashalling/serializing scheme: you will need to figure out how to tell your framework what to marshal and what not to marshal. Again, this will be highly dependent on whatever framework is in use.
1. Question
What are known strategyies, solutions for LAZY-loading from client side?
I was checking out this stuff http://wiki.eclipse.org/Introduction_to_EclipseLink_Sessions_(ELUG)#Remote_Sessions but not sure if this is a solution to my problem or how to use this.
2. Use-case
I'm developing a three tier application where my presentation layer (Eclipse RCP) is a remote client over network:
[ Eclipse RCP ] <-----(RMI)-----> [ [EJB 3] [JPA 2] [Mysql] ]
Now, I use JPA Entities as my domain model which I want to use in my client as well. I get the entites from #Session beans over network.
Problem happens when my JPA Entites have LAZY fields. After serialization and especially because my JPA provider (EclipseLink) is over the other side of the network I need a strategy to load those LAZY fields from client.
I'm going to have many entities: 30-40 maybe. And typical scenario would be when the user sees a list of SomethingModel which has many List fields, but those are not needed to be shown on the list, only when she want's to change a specific element.
3. Possible Solution
I came up with one solution e.g.: I create proxy classes for my JPA entites in client side. When I need a collection field from my Domain model, the proxy class will call the remote EJB to populate the field.
class CarModelClient {
CarModel model;
public String getColor(){
model.getColor();
}
public List<Wheels> getWheels(){
CarModelFacadeRemote carFacade = //get my remote ejb
model.setWheels( carFacade.getWheels( model.getId() ) );
return model.getWheels();
}
}
Well, similar to that.
Thank you for your answers.
Don't try to be too smart and pretend like the client was on the server, and the entity manager was always open. Consider the domain objects, at client-side, exactly as you would consider DTOs or JSON objects: objects containing some information coming from the server and seralized over the wire.
Document the service methods called from the client (the facade methods) to specify which associations are initialized and which are not in the returned entities. If you are on some "list" screen and want to see the detailed view of one of the elements of the list, for example, call another service which loads the entity again from the database (and thus gets fresh results), with probably other associations initialized in order to display more details about the entity.
Trying to dynamically initialize the lazy-loaded associations at the client just doesn't work: it's complex, inefficient, results in an obsolete and incoherent graph on the client, doesn't take transactional isolation into account.