-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Field-only navigation properties in many-to-many relationships can not be loaded by explicit loading #23717
Comments
Note, support for unidirectional many-to-many relationships is tracked by #3864. Make sure to vote for that issue. |
Before raise this issue, I searched the existed issues to avoid to raise duplicate issue. Thus I noticed issue 3864 and learned that this work is in progress. However, I will not vote for it. It is not necessary for me to hide one of the two navigation properties in this moment. I raise this issue to help others to avoid detours. This issue is added to the 6.0.0 milestone, so does issue 3864 now. Does this mean that the two issues will be solved together in a future version after 6.0.0? If it does, I think this is not what I want. My suggestion is that the right configuration should be explained as soon as possible in documentation or method description, whether the behavior of ef core is to be changed or not. From this aspect, this issue is about document rather than about a bug. If you choose to throw an exception in the WithMany() and explain it by exception message, it's also ok. |
@ajcvickers @AndriySvyryd After I change the missing navigation property to a field, query with eager loading can work, query with explicit loading still can not work. New Tag class: public class Tag
{
public int Id { get; set; }
public string Name { get; set; }
//public List<Post> Posts { get; set; }
private List<Post> Posts;
public List<Post> GetPosts() => Posts;
} And the fluent api configuration: modelBuilder.Entity<Post>().HasMany(x => x.Tags)
.WithMany("Posts")
.UsingEntity<PostTag>(
j => j.HasOne(x => x.Tag).WithMany().HasForeignKey(x => x.TagId),
j => j.HasOne(x => x.Post).WithMany().HasForeignKey(x => x.PostId)
); or modelBuilder.Entity<Tag>().HasMany<Post>("Posts")
.WithMany(x => x.Tags)
.UsingEntity<PostTag>(
j => j.HasOne(x => x.Post).WithMany().HasForeignKey(x => x.PostId),
j => j.HasOne(x => x.Tag).WithMany().HasForeignKey(x => x.TagId)
); Exception message when perform explicit loading:
I think this is not expected. I tried field-only navigation property(access by public method) with one-to-many relationship, the field-only navigation properties are loaded by explicit loading successfully. Also, I made three more queries from the other end of the many-to-many relationship (the Tag end), explicit loading failed, eager loading and projection succeeded. // succeeded
var tags = db.Tags.Select(x => new
{
x.Id,
x.Name,
Posts = EF.Property<List<Post>>(x, "Posts")
}).ToList();
// succeeded
var tags = db.Tags.Include("Posts").ToList();
//failed
var tags = db.Tags.ToList();
foreach (var tag in tags)
{
db.Entry(tag).Collection("Posts").Load();
} Exception message when perform explicit loading(notice that this one is different from above):
|
I find original issue of this post is duplicate with #23362, I omit this one when I searched the existed issues. Although I mentioned more infomation in this post, issue 23362 is raised earlier. But what about field-only navigation property? Field-only property and shadow property are two different things, right? Maybe we can use this post to trace the new issue. If the issue of field-only property can be fixed easier and earlier than #3864, then some people can use field-only property as a workaround before #3864 is solved. |
Confirmed bug in the loader. @anranruye The workaround is to use a private property instead of a private field. |
@ajcvickers will this still work with the workaround after the fix?
|
@royberris Yes. |
EF Core version: EF Core 5.0.1 / EF Core 6.0.0-alpha.1.20616.3(daily build)
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 5
Operating system: Win 7
IDE: Visual Studio 2019 16.8.0
I will use these simple entities to illustrate this issue:
When configure many to many relationship by:
An error is throwed by OnModelCreating method with error message:
System.InvalidOperationException: Unable to set up a many-to-many relationship between the entity types 'Tag' and 'Post' because one of the navigations was not specified. Provide a navigation in the 'HasMany' call in 'OnModelCreating'.
From the error message, we know that both navigations should exist in many to many relationship.
Change the code above to:
Another error is throwed with message:
System.InvalidOperationException: The navigation 'Posts' cannot be added to the entity type 'Tag' because there is no corresponding CLR property on the underlying type and navigations properties cannot be added in shadow state.
From this error message, we know that both navigations should exist and they must be CLR property rather than shadow property.
Change the code above again to :
This time no error is throwed by OnModelCreating and the model building succeeded. This is not expected.
Next step we can use the DbContext configured by the above code to do some queries.
This query with projection succeeded, which looks like a good news.
This query failed with error message:
The first query succeeded, but the explicit load failed. Error message:
The error messages of the two failed queries is not clear enough to point what is wrong. We can know that there seems to be something wrong with many to many relationship, but the first successful query will make things complex and really confusing.
I made two failed model configuring before the third one in this post. But consider that someone only use my third approach and only make query with projection rather than include(), then he can hardly notice the wrong configuration and take it as right
usage. When he use explicit load, he might be suddenly shocked.
I don't know whether this issue can be called a bug or not. But it do make trouble to me to research what is wrong. I do know that optional navigation property will be introduced by ef core 6, and this issue will not exist that time. However, before that time, a more clear tip should be made in somewhere to tell people what is the actual problem when they are tripped by the confusing error.
2020-12-20 Update:
After I change the missing navigation property to a private field, query with eager loading can work, query with explicit loading still can not work.
Look at #23717 (comment)
The text was updated successfully, but these errors were encountered: