Description
Note:
- Issues Implement many-to-many relationships without mapping join table #10508 and Many-to-many (skip) navigation properties #19003 have been created to track actual work on many-to-many relationships. The new issue is locked so that it can be subscribed to for updates on the implementation without noise.
- This older issue has been re-purposed to be discussion about many-to-many relationships in EF Core. It will not (for the time being) be locked because it is important to us that we don’t shut down channels of communication with the community.
With regard to feedback, I think it is worth reiterating some comments made a few months ago. We read and consider all feedback (and try to make the right choices based on it) no matter how it is delivered; that is, whether it is provided politely and with respect or not. Yelling at us or others with different opinions at best makes you feel good and us/them feel bad. It doesn’t achieve anything concrete. We are doing our best to prioritize features and implement them in the best way we can. We really appreciate your feedback and it makes a big difference on shaping the product. We personally appreciate it more when feedback is delivered in a respectful way, but please don’t stop providing constructive feedback.
Original issue:
I'm assuming there isn't a way to do Many-to-Many relationships in EF Core yet, as I've found nothing mentioning how to do it. Are there any examples on getting round this? Or am I just completely missing it, and it's actually there after all.
Activity
bricelam commentedon Jan 8, 2015
The workaround is to map the join table to an entity.
To navigate, use a Select:
0xdeafcafe commentedon Jan 8, 2015
Thanks!
tonysneed commentedon Jan 20, 2015
@bricelam,
Are there plans to support many-to-many without mapping the intersection table?
Also, will there be support for marking related entities as added or deleted to indicate they should be removed from the relationship and not the table? With EF6 and prior the only way to do this was to dip down to the ObjectContext API and work with independent associations. Thanks!
bricelam commentedon Jan 20, 2015
Yes, many-to-many associations will eventually be enabled via shadow state entities (#749) and skip-level navigation properties (not sure if there's a bug for that; I'll re-open this one).
I'm not sure I follow your second question, but @divega or @ajcvickers will know if it'll be covered by our "graph behavior" improvements.
divega commentedon Jan 20, 2015
@tonysneed Re your second question, not sure I understand it either, but here is some data that might help:
We should have similar default behavior in EF Core as in previous versions of EF for the general case of removing an entity from a collection navigation property: this will cause the relationship to be marked as removed, not necessarily the entity.
Removing the relationship is promoted to an actual removal of the entity for identifying relationship only, i.e. when the primary key of the dependent entity contains the primary key of the principal entity and hence the dependent cannot be orphaned or re-parented. I believe we will have similar behavior for that too, although we have talked about deferring to the SaveChanges to detect if there are orphans entities in that state rather than trying to delete them immediately. @ajcvickers can elaborate/correct me on that.
If your question is about having API that allows to control the state of relationships without manipulating the collection navigation property directly on the entity, as described in https://entityframework.codeplex.com/workitem/271, then yes, I believe that would be something nice to have, however we haven't prioritized it. Your feedback would be helpful.
Does this help answer your question?
tonysneed commentedon Jan 20, 2015
@bricelam, thanks for answering my first question. I'll be interested to learn more about implementing many-to-many via shadow state entities.
@divega, I'll clarify my second question. Let's say I have two entity classes that have a many-to-many relationship, for example, Employee and Territory from the Northwind sample database. If I wanted to add or remove a Territory from Employee.Territories, in a disconnected fashion using EF6, I would not be able to do so by setting EntityState on the Territory to Added or Deleted. Instead, I would call ObjectStateManager.ChangeRelationshipState, specifying the property name. Since ObjectContext is going away in EF Core, I'm just wondering how changing relationship state will work for entities in many-to-many relationships when performed in a disconnected manner (for example, from within a Web API controller). Hopefully this helps clarify my question a bit. Thanks!
tonysneed commentedon Jan 21, 2015
Alight, I think I can clear everything up now that I've had a chance to try out a few things. The way to add or remove entities from a relationship in a disconnected fashion in vCurrent is not very straightforward or consistent when it comes to many-to-many relations. Stating that it is not possible without resorting to the OSM was incorrect. It can be done via the DbContext API but it's awkward. And what I'm wondering is if the API for EF Core could be improved to allow direct manipulation of the relationship, similar to what could be done via the OSM (albeit without needing to specify the navigation property name)?
For those following this conversation, here is what the OSM API looks like in vCurrent:
So let's start with the vCurrent behavior of adding and removing entities from a m-m relation. Assuming that Employees and Territories have a m-m relationship, if I add a territory to an employee, then the territory will be marked as Added and EF will attempt to add it to the Territories table. If I want to just add the relationship to an existing territory, then I need to explicitly mark it as Unchanged, which makes sense but isn't all that intuitive. It's also inconsistent with the behavior for removing entities from a relationship, where removing a territory from an employee will not mark it as Deleted, without the need to explicitly mark it as Unchanged.
It seems to me that the remove behavior is a bit more straightforward. Adding a territory to the Territories collection of an employee could also leave it in an Unchanged state but result in adding it to the m-m relation. Then explicitly marking the entity as Added or Deleted would mean that you wanted to add to or remove from the Territories table as well as the m-m relation. This is the behavior that I would recommend for EF Core.
So this leads to the question of an API that would let you deal with the relationship directly. My question (which is hopefully clear by now) is whether could be a way in EF Core to change the state of a relationship. Following the proposal from CodePlex issue 271, it could look something like this:
Even though may look somewhat intimidating, the important thing would be the ability to use the API from within the callback for AttachGraph (#1248), which is an Action. But for this to work, there would have to be a way to infer how the current entity in the graph is related to its parent (1-1, M-1, M-M). (This is what I do in my Trackable Entities project.) So we might need to add an overload of AttachGraph as follows:
I'm probably getting this wrong, but we would need a parameter that represents how the current entity being iterated is related to its parent. (Here DbMemberEntry represents the navigation property and the second EntityEntry represents the parent of the current entity.) That way, we could figure out what kind of relationship it is and use the correct approach to attach the entity. Please let me know if I'm making sense here. :)
Cheers,
Tony
[-]Many-to-Many relationships[/-][+]Many-to-Many relationships (without CLR class for join table)[/+]ctolkien commentedon Jul 27, 2015
Just chiming in on this issue. Many-to-many is the one scenario that is blocking us from EF Core adoption. I realise that you can use intermediate mapping classes, but that requires significant changes to how we'd like to model things.
I note this is still tagged for the backlog. Is this feature on the roadmap for v1?
damccull commentedon Jul 27, 2015
Sooo....gimme. Many-To-Many is probably the only thing left that I NEED in order to do what I want...I WANT more features, but many-to-many is all I NEED...probably.
496 remaining items
AndriySvyryd commentedon Sep 27, 2020
@vslee We don't have any plans to support this pattern.
jzabroski commentedon Sep 30, 2020
@AndriySvyryd Is there a ticket in the backlog for it? It seems like that pattern would allow some join optimizations under certain conditions.
AndriySvyryd commentedon Sep 30, 2020
@jzabroski No, feel free to open one and include the expected schema and query if possible.
robertechie commentedon Jul 29, 2021
how can you link 3 tables together without setting the joining table as specified in core 5?
jzabroski commentedon Jul 29, 2021
@robertechie Did you read the documentation before posting your question?
davidbuckleyni commentedon Oct 2, 2021
Has this been sorted yet or do we still require the backing table EF 5.10
davidbuckleyni commentedon Oct 2, 2021
Sorry this is indeed the correct link to docs.
https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-5.0/whatsnew
samuelhurni commentedon May 1, 2022
I want to use many to many relationship in my Project with EF Core 6. I have already understood that there are changes in EF Core 5 that you don't have to declare the joning table, so with the "Icollection", and ""Icollection" at both sides the joining table will be created behind the scenes.
But my question is about to implement the update and delete sequences for relations. I havnt' found a documentation after this update to implement the sequence to add relationsships between two Entitys with many to many relation without accesing the joining table directly from the code. I have also problems how to delete a many to many relationship.
My first idea was to get an entity for example of Class A and include also the ICollection of the other related class (Class B). After that I modify this Collection of Objects of ClassB, for example Add a new Object B or delete one Index of an Object of Class B. This I have to do at my Frontend side. When I did the changes, I want to update this with an Update Endpoint at my backend. So in my backend repository I will recive the modified Class A object , maybe with other relations in the ICollection List of Class B.
Then I want to trigger the database.Update(), Method and after that the database.SaveChanges() Method. With this approach it is not working fine. Sometimes I have the error "Insert Error in Table ClassB Duplicate Primary Key ", so EF Core want to insert a new Entity in Table ClassB instead of only set a new relation in the joining table. Other Issue is that when I remove one Object of ClassB in my ICollection of ClassA at my Frontend and trigger the Update Endpoint of my Backend, EF Core not deetect the missing object of ClassB in my ClassA Entity and not delete the joining tabel relation.
Here an Example of my Update Repository of a Table Book. The Book has a many to many relation to the Table Author:
`
`
And here I get the book for doing changes included the ICollection of Authors:
`
`
So is there a godd documentation somewhere how to modify many to many relations without using the joining table directly in the programm code. Because this update of creating the joining table behind the scenes in EF Core 5 is great but is not useful when the updating data is not working behind the scenes for the joining table.