EF6 Relationships
I have two classes built in EF Core, that I used to scaffold the database and use in the frontend Blazor app.
Now, building and using this in Blazor is fine. However, I also need the table in a .NET Framework app. So I've ported the DB model to EF6 just to simply use the context for accessing the database and the models without writing the queries manually. However, EF6 refuses to work with this due to the relationship. It throws an error for
Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.
What solutions are there for getting around this? I have to use .NET Framework, and building an API is overhead that's just not needed.75 Replies
if StreamPointIntegrationELogger contains a StreamPointListenerStep then shouldn't StreamPointIntegrationELogger field be an inverse property?
No, the step contains the ELogger
I previously had the ELogger ID on the Step, but that caused a FK in both tables which didn't make sense. Thinking about it, the ID should be on Step, and no ID on ELogger. It should be 1-1, so that should fix that then
it depends in which direction you need the relationship
A Step has an IntegrationElogger. Step->ELogger, it can't be the other way around
And I don't see there being a need to re-share the ELogger, so it should only be 1-1
from a technical point of view you place the fk where you want, right? it's more of a matter of what is the meaning of it
if you have the fk in the Step then every time you add an "extension" class you have to add an fk column in that class, which means modifying it
if you keep the fk in the ELogger class then you don't need to change Step
just as an example, there are other cases
Yeah, the FK needs to be on Step
And that resolved that issue, but now there's a new one I haven't seen before
DbComparisonExpression requires arguments with comparable types.
trying to see if it actually gives something useful
Nevermind, I was trying to send a string as the Guidif it's a 1-1 it could even be an owned type
One other question if you're still able to help. I want eager loading....but only for properties I specifically tell it to load. I don't understand why they build the system this way
That causes this property
Points
on PiCollective
to be loaded automatically. I don't want that, nor did I specify it. So why in the world is EF loading it?
if you specified
.ThenInclude(p => p.PiCollective)
then it will load all of PiCollective
's properties. hard to tell what's what without the model.
BUT, you should most likely be creating a DTO here since i see you're returning the result somewhere. So project your result to a DTO (.Select(x => new DTO{...}
before ToListAsync) and then you don't have to worry about including values.Yeah, I get the DTO approach. It's just a stupid way to design the system - creating more work for no reason because the tooling isn't sufficient.
I'll be able to get around this particular problem by not doing the ThenInclude, and pulling the data ref another, more efficient way. But it's something I'll need to consider.
its usually not a good idea to pass around entities directly anyway. keep them next to the dbcontext they are pulled (tracked) from.. then you cant end up adding them to a different dbcontext or something. keeps your data flow sane.
and creating a dto these days is as simple as
record Whatever(...)
🙂 not much workI despise entity tracking and turn that crap off anyway
It's not a stupid way to design the system, I don't get what you're talking about
You're starting from X, loading Y, and then loading Z
And you're complaining that loading Z loads Y?
No, I'm starting from X and loading X. If I want Y, I'll tell EF I want Y, otherwise I don't want it.
That's exactly what you're saying with
Include
No, because it's including things that I'm not telling it to include.
Like what?
If I have
Library
with Book
s and Author
s on each books, and I say ctx.Libraries.Include(x => x.Books).ThenInclude(x => x.Authors)
, the collection Books
will be populated on the Author
So given that example above, that
.ThenInclude
causes a recursive loop (due to the properties which I'll show). If I wanted an endless loop, I would have told it to give it to me.No.
It's not endless.
The entities already loaded by the context will be populated.
Given this code, it is called once. It will return a loop of PiCollective with Points which then contain the Collective which then contains the points. I only want 1 level of depth (the depth of which I have explicitly stated)
There is only one level of depth.
No, there isn't lol
Only one level will be loaded.
Nope.
That's why I had to remove the ThenInclude, or tell the JSON parser to ignore recursive loops.
Well, all of the levels which are possible with
PiCollectivePoint
will be loaded
UhhhWhich is stupid. If I wanted that, I would include that in my query.
No
Your first mistake is JSON Serializing DB entities
Your second mistake is assuming there are multiple levels
There only needs to be one level for that issue to occur.
I'm not assuming. It's literally in the debugger when you view the results.
var book = ctx.Books.Include(x => x.Author).First()
This will load one book.
book.Author
- this is populated
book.Author.Books.First()
- this is populated
book.Author.Books.First().Author
- this is populatedWhen I use that
.ThenInclude
, it populates Points
- which I don't ask for, which then populates Points, which populates the Collective, which gets the Points again.It's fulfilling relational navigation on the entities.
It's doing its job.
And I don't want it to
I want it to do what I told it to do
Then don't include
Books
on Author
Or use separate queries.
EF's JOB is to hook up C# entities to the results of DB queries.The other methods for retrieving data make it less efficient and more convoluted.
You're asking for it to not do the thing people use it for.
Your misunderstanding of the tool does not mean it's shit, or that "it's not doing what I tell it to"
The purpose is to reduce work, not introduce work.
It introduces work for those who don't bother understanding what it does.
Eager Loading of Related Data - EF Core
Eager loading of related data with Entity Framework Core
Within the top half of the page
Less than 15 seconds of my time to find this information
Your mistake is serializing a DB entity which can naturally have cyclical relationships.
This is not EF's fault, this is not JSON's fault, it is yours.
Converting something like this to explicit loading just doesn't make sense, especially where they don't even support loading lists in bulk.
I won't even comment on the absurdity of that query, but "loading lists in bulk"?
Exactly, and yes, all that data is required for a process to operate correctly. So according to what I found, if I wanted to query those records using .ToList, but using the explicit method, I’d also have to introduce a loop to explicitly load the paths. And even then, the official documentation is broken and doesn’t work.
The official documentation is not broken, your understanding or usage is likely what's broken.
There would be no loop needed.
Using a loop to load a series of related data is obviously highly inefficient
It's absolutely not a stupid way to build a system.
Your queries are equivalent of doing
SELECT * FROM Foos
.
Your queries are heavy and inefficient, that's what's stupid.
Anyone who queries SQL in a typical way would do SELECT Bar, Baz, Qaz FROM Foos
.
Throwing AsNoTracking
on there and including everything is an anti pattern.
Blaming the tooling for being wrong, when you're not using it in its intended way is not a resolution.Not once has anyone provided documentation showing the “proper” way to do what’s needed. And just because you might not need all data from certain relationships, doesn’t mean there aren’t cases for processes that do.
That being said, if the documentation on explicit loading isn’t broken, then why does VS throw an error for using the exact pattern as documented? Have you tried it yourself like I have? There’s a GitHub issue on the usage of selecting a list of objects from the DB using that method because it’s not supported.
Efficient Querying - EF Core
Performance guide for efficient querying using Entity Framework Core
Efficient Querying - EF Core
Performance guide for efficient querying using Entity Framework Core
then why does VS throw an error for using the exact pattern as documentedbecause it's your code that is the problem 🙂
https://learn.microsoft.com/en-us/ef/core/querying/related-data/explicit looks like a language issue to me
I don't understand your message.
What you're doing isn't legal.
It's literally in the documentation I linked lol
Your code isn't 1:1 with the documentation ,then 🙂
Documentation isn't accurate
Not the first time a vendor has inaccurate docs, but it's fine
Hard to say when you don't actually post your code
I posted the model above earlier between those entities
you've posted irrelevant snippets
You want all 10 classes, or just the two classes with the relevant paths?
whatever type
StreamPointListeners
is and its memberswhat a surprise
your code isn't right 🙂
Actually, that was added after the code testing last night. I never include those virtuals lol
Collection
is used for a collection, not a singular nav prop
so the document is accurate, your code is just wrongBut for the second document you linked for making more efficient queries, if I didn't need columns, then I wouldn't have the columns in the first place. They're needed for a reason in 99% of scenarios.
that doesn't make logical sense
you own a house, you don't use every room of the house every day, all day
not every piece of code requires every single column from an entity
They're used in their respective processes. The processes need the data to run.
No, not every piece of code does. Only the relevant classes do. And those classes are the only ones that access the data anyway.
you're literally arguing against industry specialists
the fact you've put AsNoTracking on your queries is enough of an indicator that you're bastardising to do something you can do in a much better way
Again, no. Hard tracking the models sucks.
you've repeatedly said the documentation is wrong, when I've just proven it's your code, said the tooling is inadequate, when it's your practices and now argue that the practices championed all across the industry are wrong.
i have no interest in continuing this conversation.
good luck.
The model is either getting updated or used. There's no inbetween where all the columns aren't required.