-
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
How to saturate an ICollection navigation property in a view? #19890
Comments
@dharmaturtle Is there a specific database schema that you need this to map to? If so, can you post it? |
I've uploaded a minimum working example here: https://github.com/dharmaturtle/EFViewAndManyToMany The latest commit's modelBuilder looks like:
However, it causes this error to occur:
|
@dharmaturtle I've spent some time looking at you code but I'm still not sure what you are trying to achieve. What is the purpose of |
It's supposed to be a minimal working example. |
@dharmaturtle EF Core doesn't allow the same database relationships to be mapped to more than one different entity type. In the code you posted, both This is not something I have seen people try to do before. I will discuss with the team whether we should support this in some way. |
Would a reasonable workaround be to create a new FK between the view and the table I want to JOIN on? (...is that even possible in MSSQL?) |
@dharmaturtle I'm still not sure exactly what you are trying to achieve so I'm going to go into more detail in several areas. Some of this may not be relevant. Querying stored proceduresFirst, let's assume you have a defined model with no views. To keep it super simple, something like this: public class Blog
{
public int Id { get; set; }
public ICollection<Post> Posts { get; set; }
}
public class Post
{
public int Id { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
} Now let's say I add a PostView to my database that can return Post entities. I can use it like this: var posts = context.Posts.FromSqlRaw("SELECT * FROM PostView").ToList(); This generates: SELECT * FROM PostView I can also compose over this, for example, with Include: var posts = context.Posts.FromSqlRaw("SELECT * FROM PostView").Include(e => e.Blog).ToList(); SELECT [p].[Id], [p].[BlogId], [b].[Id]
FROM (
SELECT * FROM PostView
) AS [p]
INNER JOIN [Blogs] AS [b] ON [p].[BlogId] = [b].[Id] In addition, see #17270 for more work in this area we are doing for EF Core 5.0 The critical thing to notice here is that I did not create a new CLR type for PostView. Projecting to different typesLeaving views aside for the moment, EF does allow me to project from my entity types to other CLR types. For example: public class BlogDto
{
public int Id { get; set; }
}
public class PostDto
{
public int Id { get; set; }
public int BlogId { get; set; }
public BlogDto Blog { get; set; }
} var posts = context.Posts.Select(e => new PostDto
{
Id = e.Id,
BlogId = e.BlogId,
Blog = new BlogDto
{
Id = e.Blog.Id
}
}); I can also combine this with using a view: var posts = context.Posts.FromSqlRaw("SELECT * FROM PostView").Select(e => new PostDto
{
Id = e.Id,
BlogId = e.BlogId,
Blog = new BlogDto
{
Id = e.Blog.Id
}
}); SELECT [p].[Id], [p].[BlogId], [b].[Id]
FROM (
SELECT * FROM PostView
) AS [p]
INNER JOIN [Blogs] AS [b] ON [p].[BlogId] = [b].[Id] What doesn't workThe thing that doesn't work is trying to use a mix of CLR types in different ways in different places. For example: public class PostDto
{
public int Id { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; } // Uses Blog here
} This results in an ambiguous model where relationships and FKs may have different meanings in different contexts. Hopefully this makes things a bit clearer. |
Given the following, how can I saturate
Post_Tag
?This works:
But this does not:
It throws this error:
It works if I drop the
HasNoKey
in themodelBuilder
, but this doesn't scale; subsequently attempting to saturateAuthor_Tag
usesPostViewId
which doesn't exist. I could solve this by naming a key (e.g.[Key]
), but then I would be stuck with one key per view. I could also solve this with query syntax and explicitly naming theJOIN
predicate, but for various reasons I want to avoid that.Here's the code, error, and generated SQL if I drop the
HasNoKey
(Lastly, why is there an
ORDER BY
?)Thanks!
Further technical details
EF Core version: 3.1
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: NET Core 3.1
Operating system: Windows 10
IDE: Visual Studio 2019 16.3
The text was updated successfully, but these errors were encountered: