What is the best practice for managing relationships using POST and PATCH in a RESTful API when the opposite entity already exists? - rest

I am designing a RESTful API and my questions is the following: What is the best practice for managing relationships using POST and PATCH in a RESTful API? Where and when should I allow the consumer of the API to establish relationships between entities when the opposite entity/entities already exists/exist? My goals are to (a) minimize code and code maintenance with (b) a balanced ratio of easiness to understand the API and number of API calls to establish relationships. The most limiting criterion is that I am developing and maintaining the API on my own.
If it is of any interest, I am using ASP.NET Core and separated the API (with outer facing models) and the entity framework based data layer (with data models) into two different layers, where the API layer references the data layer (API -> Data).
I would like to discuss all possible combinations of the http request methods POST and PATCH and the three types of relationships one-to-one, one-to-many and many-to-many.
POST one-to-one
I was thinking about allowing the consumer of the API to let the POST request for the new entity only go through when the opposite entity has no relationship to any other entity of the posted entity type.
Another option would be to never allow setting relationships through POST but only let it update via PATCH. I favor this option, because it makes the entity easier and saver to create when treating the relationships separately. Even better, it would only require two API calls - one for POSTing the new entity and one for PATCHing even multiple relationships to many different one-to-one opposite entities.
POST one-to-many
One option would be allowing the consumer of the API to let the POST for the new entity only go through when all of the opposite entities have no relationship to any other entity of the posted entity type. Less save would be to allow the consumer to override existing relationships of the opposite entity to another entity of the type of the posted entity.
Another option would be to not allow posting any relationship of a single entity to many entities, because the relationships are effectively set in the opposite entities anyway. I prefer to only allow setting the relationship in the opposite entities via PATCH since this is the place where the many to one relationship is effectively established, and it keeps the creation of the entity separated from establishing relationships.
POST many-to-many
I would never allow to set a relationship for a POST request in a many-to-many relationship, but only allow to PATCH new relationships on both the new entity and the opposite entity. Due to the complexity of this type of relationship, I think it is best keep the entity creation as easy as possible and manage relationships separately through PATCH requests.
PATCH one-to-one
I would set no restrictions and allow the consumer of the API to set the relationship freely on both sides.
PATCH one-to-many
This one is a real dilemma for me - number of API calls vs easiness to understand relationships and lines of code.
On the one hand, I could allow to PATCH from the single entity point of view (it contains for example an array of opposite entity IDs). This would require only one API call to update the relationships of the multiple opposite entities, but this requires more code, because the data layer needs find and loop through all opposite entities. In addition, updating from the single entity point of view is sometimes hard to understand for me - many times its easier for me to establish the relationships in all opposite entities that refer to the same single entity.
On the other hand, I could allow the consumer of the API to update all opposite entities individually. This would require many API calls, but I sometimes think updating from this point of view is easier to understand, and the relationship is effectively set in the multiple opposite entities anyway.
I don't know what to favor yet. I am thinking about offering both options.
PATCH many-to-many
The only way I can see is to allow the consumer of the API to allow setting relationships on both sides due to the nature of this relationship.
While elaborating my ideas above, I think the best guideline is to keep creation of entities completely separated from establishing relationships and to set the relationships only where they are effectively established (mimicking SQL table behavior). I assume the latter one is what most API consumers should be familiar with and the first one keeps the API save and simple (at the cost of efficiency).
Please let me know if I missed any cases, criteria for decision making or didn't think of any implementation strategies.
Best regards,
philippfx

Related

Structuring nested rest API

I'm writing an API with spring boot, trying to keep it restful but the structure is quite nested. So say I have:
/api/examboard/{ebid}/qualification/{qid}/subject/{sid}/module/{mid}/
I have a controller for every noun that will take in all Id's, the problem with this is that I don't really need an ebid or a qid for modules, they only really need to be concerned with subjects most of the time. The mapping between them all is quite simple. An examboard will have many qualifications, a qualification will have many subjects etc....
Now the problem is say I go for a simpler API design where I only need the parent Id so the Subject controller will also have:
api/subject/{sid}/module
then I need to include multiple services in my controller based on the way JPA works. As I need to include SubjectEntity based calls and ModuleEntity based calls. However I want to maintain a one to one relationship between my controllers/services and services/repositories. This is why I opted for the longer url as I've mentioned above, but it does seem like overkill. Does anyone have any advice on how I should structure an API like this, most examples are quite small and don't really fit.
Without knowing more about your models and the relations between them, this answer will have to stay a bit diffuse.
First of all - "it depends". I know, but it really does. The way you should design an API depends heavily on your use cases that will define required access patterns. Do you often need all modules for a subject? Then introduce /subjects/{sid}/modules, if you need the details for a module of a subject in a qualification in an examboard - by all means have a /examboards/{ebid}/qualifications/{qid}/subjects/{sid}/modules/{mid}
As you say there are many relations between your entities. That is fine, but it does not mean that you need your API to capture each of these relations in a dedicated endpoint. You should distiguish between retrieving and modifying entities here. Find below examples for certain operations you might want to have (not knowing your models, this may not apply - let's consider this an illustration)
Retrieve qualifications for an examboard
GET /examboards/{ebid}/qualifications plain and simple
GET /qualifications?ebid={ebid} if you feel you might need sophisticated filtering later on
or create a new qualitication for an examboard
POST /examboards/{ebid}/qualifications with the details submitted in the body
POST /qualifications with the details submitted in the body and making the associated examboard ebid part of the submitted data
or update an existing qualification
PUT /qualifications/{qid} (if this operation is idempotent)
POST /qualifications/{qid} (if it should not be considered idempotent)
or delete qualifications
DELETE /qualifications/{qid} deletes entities, cascade-deletes associations
DELETE /examboards/{ebid}/qualifications clears all qualifications from an examboard, without actually deleting the qualification entities
There are certainly more ways to let an API do all these things, but this should demonstrate that you need to think of your use cases first and design your API around them.
Please note the pluralisation of collection resources in the previous examples. This comes down to personal preference, but I tends to follow the argumentation of Sam Ruby in RESTful Web Services (available as PDF) that collections should be first-class citizens in an API
Usually, there should not be a reason to have 1:1:1 relationships between controllers, services and repositories. Usually, this is not even possible. Now, I don't know the reason why you might want to do this, but following through with this will force you to put a lot of logic into your database queries and models. While this (depending on your setup and skills) may or may not be easily testable, it certainly shifts the required test types from unit (simpler, usually faster, more fine-grained) to integration tests (require more setup, more complex, usually slower), when instead of having the bulk of your business logic in your services you put them into many joins and subselects in your repositories.
I will only address your REST API structure question.
As you already pointed out
The problem with this is that I don't really need an ebid or a qid for modules, they only really need to be concerned with subjects most of the time
You need to think of your entities as resources if your entity can stand for itself give it its own top level resource. If instead your entity exists only as a part of another entity build a subresource below its parent. This should correspond with the association type aggregation and composition in your object model design.
Otherwise every entity that is part of a many relationship should also be accessible via a subresource on the other side of the relationship.
As I understood you you have a OneToMany relationship between examboard and qualification so we get:
api/examboards/{eid}/qualifications
api/qualifications/{qid}/examboard
Yo could also remove the examboard subresource and include it in the qualification response.
For ManyToMany realtionships you need two subresources:
api/foos/{fid}/bars
api/bars/{bid}/foos
And another resource to manipulate the relationship itself.
api/foosToBars/{fid}+{bid}
Or likewise.

Should Entities in Domain Driven Design and Entity Framework be the same?

I have started using Entity Framework Code First for the first time and am impressed by the way in which our greenfield application is being built around the domain rather than around the relational database tables (which is how I have worked for years).
So, we are building entities in C# that are being reflected in the database every time we do a new migration.
My question is this: should these same entities (i.e. designed with Entity Framework in mind) play the same role as entities in Domain Driven Design (i.e. representing the core of the domain)?
Object-Relational Mapping and Domain-Driven Design are two orthogonal concerns.
ORM
An ORM is just here to bridge the gap between the relational data model residing in your database and an object model, any object model.
An Entity as defined by EF concretely means any object that you wish to map some subpart of your relational model to (and from). It turns out that the EF creators wanted to give a business connotation to those by naming them Entities, but in the end nothing forces you that way. You could map to View Models for all it cares.
DDD
From a DDD perspective, there's no such thing as "an Entity designed with EF in mind". A DDD Entity should be persistence ignorant and bear no trace of any ORM. The domain layer has no interest in how, where, whether or when its objects are stored.
Where the two meet
The only point where the two orthogonal concepts intersect is when the object model targeted by your ORM mapping is precisely your domain model. This is possible with what EF calls "Code first" (but should really be named regular ORM), by pointing to your DDD Entities in separate EF mapping files living in a non-domain layer, and refraining from using EF artifacts such as data annotations directly in your Entity classes. This is not possible when using Database First, because the DDD "purity" part of the deal wouldn't be met.
In short, the terms collide, but they should really be conceptually considered as two different things. One is the domain object itself and the other is a pointer that can indicate the same bunch of code, but it could point to pretty much anything else.
They shouldn't be the same as they're designed for different purposes. An ORM entity is a facade for 1 or more tables, its purpose is to simulate OOP on top of relational tables. A Domain Entity is about defining a Domain concept. If your Domain Entity turns out to be just a data structure, then you can reuse it as an EF entity, but that's just one case.
A DDD app never knows about EF or ORM. It only knows about a Repository. Hence, your Domain Objects (DO) don't know either about EF. You can choose to consider them EF entities, as an implementation detail, BUT... you should do that ONLY after your DOs are defined and their use cases implemented. You should defer as much as possible the implementation of persistence (use in-memory repos (lists) for devel).
When you reach that point you'll know if you can reuse your DO for ORM purposes or if you'll need other ways (such as a memento).
Note that a design of a DO while driven by the Domain, it should take into consideration the persistence issue, but it shouldn't be influenced by it i.e don't design your DO according to the db schema. The persistence strategy can be different for each DO and it might involve or not an ORM.
If you're using Event Sourcing for a DO, ORM doesn't exist. Same for serialized objects. It matters a lot how an object will be used by the app (updating and querying), that's why I've said you should defer the persistence implementation. For a lot of DOs you won't need a rdbms (even if you're using it) so an ORM entity will look more like a KeyValuePair (Id => serialized data).
In conclusion, they are different things for different purposes, that might look identical for some cases (CRUD scenarios).
I would say, they can be the same.
Sometimes there is no need to support two models. When you follow code first approach, your entities model your domain, your infrastructure (ORM) separates domain and persistence layers.
It might be reasonable to maintain two models if you have legacy database and have to maintain it.
There are two other SO questions that can be helpful:
Repository pattern and mapping between domain models and Entity Framework
Advice on mapping of entities to domain objects
Well.That's The Approach i use.And I've seen a lot of others doing the same.Now am using The Onion Architecture/Pattern to Create my application and making Everything rely on the domain entities made my life easier.because whenever i want to change for example the Layer that deal with my database ,i can do that without changing the UI layer(ASP.NET MVC app,WPF app...etc)...I suggest doing the same.
let's wait for other posts
I agree with what MikeSW said (3rd Answer).When you design your domain entities,you should do that without caring about who will consume those entities (ORMs or any other technology serving whatever purpose).design them with one idea in mind : they will be reusable and they will not need to be changed in the future (hopefully)

What is included in DbContext model?

Description:
I've tried to separate certain domain segments into different DbContexts.
Each has several DbSets, but there are some DbSets that are shared, for example the UserProfile.
The reason for this separation is the speed at which the model is generated and the simplicity (less sets in an object, helps with intellisense).
However, I am not sure about what exactly belongs to the model that is generated.
Q1: Is every entity that is transitionally connected with the entities, for which a DbSet exists in a DbContext, included in the model?
Q2: If so, would that mean that performance-wise it serves no purpose to separate the domain into different contexts, since everything that is connected ends up in the model anyway, no matter which DbSets are stated in the DbContext?
Where can I find more information on how the model is generated? I've read a book on EntityFramework and CodeFirst and couldn't find that specific information...
Answering your first question: yes, all relations are modeled including the entities on both sides, so every entity that's connected by a navigation property to an included entity will also be included in the model regardless if there's a DbSet for it or not.
Entity Framework doesn't force you to create DbSets for all entities. This can be handy if you want to "restrict" child entities to only be accessible through their parents.
Regarding your second question: separating your contexts might still improve performance, if not all entities belonging to one context are reachable via navigation properties of entities belonging to the other context. There could be an additional cost associated with explicitly including more DbSets in a context, too.
You could read (some parts of) the Entity Framework source code, it's open-source and available on CodePlex to learn more about how the model is built.

ORM Entities vs. Domain Entities under Entity Framework 6.0

I stumbled upon the following two articles First and Second in which the author states in summary that ORM Entities and Domain Entities shouldn't be mixed up.
I face exactly this problem at the moment as I code with EF 6.0 using the Code First approach. I use the POCO classes as entities in the EF as well as my domain/business objects. But I find myself frequently in the situation where I define a property as public or a navigation property as virtual only because the EF Framework forces me to do so.
I don't know what to take as the bottom line of the two articles? Should I really create for example a CustomerEF class for the entity framework and a CustomerD for my domain. Then create a repository which consumes CustomerD maps it to CustomerEF do some queries and than maps back the received CustomerEF to CustomerD. I thought EF is all about mapping my domain entities to the data.
So please give me some advice. Do I overlook an important thing the EF is able to provide me with? Or is this a problem which can not completely solved by the EF? In the latter case what is a good way to manage this problem?
I agree with the general idea of these posts. An ORM class model is part of a data access layer first and foremost (even if it consists of so-called POCOs). If any conflict of interests arises between persistence and business logic (or any other concern), decisions should always be made in favor of persistence.
However, as software developers we always have to balance between purism and pragmatism. Whether or not to use the persistence model as a domain model depends on a number of factors:
The size/coherence of the development team. When the whole team knows that properties can be public just because of ORM requirements, but should not be set all over the place, it may not be a big deal. If everybody knows (and obeys) that an ID property is not to be used in business logic, having IDs may not be a big deal. A scattered, unexperienced or undisciplined team may need more stringent segregation of code.
The overlap between business logic concerns and persistence concerns. Object oriented design thrives when a class model sticks to SOLID principles. But these principles are not necessarily at odds with persistence concerns. I mean that although the concerns are different, in the end their resultant requirements may be quite similar. For instance, both concerns may require valid object state and correct associations.
There can be use cases, however, in which objects temporarily need to be in a state that absolutely shouldn't be stored. This may be a reason to work with dedicated domain classes. Another reason may be that the entity model just can't fulfill the best segmentation of responsibilities. For instance, a business process "blacklisting customer" may require data that is scattered over so many entity objects that new domain classes must be designed that can encapsulate the data and the methods working on them. In other words: doing this by entities would violate the Tell Don't Ask principle.
The need for layering. For instance, if the data access layer targets different database vendors it may have to consist of interchangeable parts that are vendor-specific (e.g. to account for subtle differences in data types between Oracle and Sql Server or to exploit vendor-specific features). Using the persistence model as domain model would probably bleed vendor-specific implementations into the business logic. That would be really bad. There the data access layer should be precisely that, a layer.
(Very trivial) The amount of data. Creating objects takes time and resources. When "many" objects are involved in a business case it may just be too expensive to build both entity objects and domain objects.
And more, undoubtedly.
So I would always try to be a pragmatist. If entity classes do a decent job, go for it. If the mismatch is too large, create a business domain for appropriate parts of the business logic. I would not slavishly follow a (any) design pattern just because it is a good pattern. Contrary to what is said in the post, it requires a lot of maintenance to map an entity model onto a business model. When you find yourself creating myriads of business classes that are almost identical to entity classes it's time to rethink what you're doing.

Is it good practice to model to-one relationships in only one direction? Or must they be modeled in two directions?

In Core Data, most of the time relationships are modeled bidirectional. But the docs say in another place:
It typically only makes sense to model
a to-one relationship in one
direction.
Within Core Data you should always use a bi-directional relationship unless you have an extreme edge case. If you use one directional relationships then you are going to incur performance penalties within core data itself as well as have issues with referential integrity.
Unless you know specifically why you need a uni-directional relationship then you should always do a bi-directional relationship; the rule is that simple.
While Franci's answer is interesting, I have to disagree with it. Even in the examples he provided you should have a bi-directional relationship. There are almost no situations where a uni-directional relationship is going to be a better fit.
The answer is determined by the referential integrity requirements you want to enforce. If updating or removing the object on either side affects the object on the other side of the relationship, you need two-way. However, if updating/removing the object on one side does not affect the object on the other, then a one way is a better model.
Take for example a parent-children model with a 0..n : 1 cardinality (I prefer the 1 : 0..n representation, but for the sake of argument let's reverse it). Adding a new child, updating an existing child or deleting a child has no effect on the parent object, so there's no need for the parent to know explicitly about all the children (except when it comes time to pay college tuition). However, removing the parent has an adverse effect on the children objects, as they need to be deleted or re-parented, otherwise are orphaned and in an invalid state. Thus, it's better to model it as a one-way relationship. Another example is inventory - parts catalog relationship, again with 0..n : 1 cardinality.
It's a matter of ownership: usually it doesn't make sense to have a bidirectional relationship because an entity conceptually owns the other one.
Think about some examples. If you have a structure in which you have users and an user can have a simple bank account associated with him. If you make the relation bidirectional you mean that an user owns an account but also an account owns an user.
This will make sense because you don't want to delete an user whenever you delete his account. That's why usually you don't need to have it bidirectional: because it's an additional constraint that is not needed since most of the time you will have an entity that has the other but not vice-versa.
I think you read the whole document about relations you referenced in your question.
The document also describes all disadvantages of using unidirectional relations, and that only under very rare circumstances it makes sense to create unidirectional relations.
As a general rule i would strongly recommend creating bidirectional relations, except you are knowing exactly why not to do so.