-
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
Improve exception for One-to-many from Keyless Entity Type #24283
Comments
There is a conflict between |
Thanks for your reply, but that's not the problem: it's the call to |
@optiks I want to point that, you should use regular entity for modelBuilder.Entity<vwContainerSource>(entity =>
entity
.HasKey(d => new { d.CompanyShippingId, d.ContainerNumber })
//.HasNoKey()
.ToTable("vwContainerSource") //vwContainerSource is a database view
.HasMany(d => d.ShippingLineContainerTariff)
.WithOne()
.HasForeignKey(d => new { d.CompanyShippingId, d.ContainerNumber })
//.HasPrincipalKey(d => new { d.CompanyShippingId, d.ContainerNumber })
); Also, you should change your migration file manully if you use migration. Remove the table and foreign key creation code. And create foreign keys for underlying database tables of |
@anangaur Thanks again for your reply.
As I mentioned in Expected Result, the bug isn't that this scenario isn't supported, it's that the result of invoking the unsupported path is a
We're already using "regular entities" as a workaround, but it feels like a hack, to me. We want the standard Keyless Entity Type benefits (changes aren't tracked, not discovered by convention, HasNoKey), and I don't really see why having a primary key defined (which isn't even used in the relationship) is necessary? |
An sql query that returns both parent and child properties, must be able to step through the flat result set, recognise which rows in the result set map to the same parent object, materialise the child objects and link them to that parent. This is impossible without a key on the parent. Sure, a better error would be good though. |
Thanks, good reply. I see the problem, but I also see two potential solutions (although admittedly I haven't thought them through that deeply...):
vwContainerSource (P)
ShippingLineContainerTariff (C)
After joining on SELECT P.*, C.*
FROM (
SELECT (SELECT NEWID()) AS RowGroup, *
FROM vwContainerSource
) P
LEFT OUTER JOIN ShippingLineContainerTariff C ON P.CompanyShippingId = C.CompanyShippingId AND P.ContainerNumber = C.ContainerNumber
During materialisation, I'd expect:
Wouldn't this work? |
@optiks Nice to talk to you again. :-) First, the Second, EF Core needs to be able to uniquely identity the parent entity. If such a set of columns exist, then they should be defined as the key for the parent type. It doesn't matter if their is such a key in the database or not; it just needs to provide a unique identifier for each row read. Once the principal type is no longer keyless, then a relationship can be defined to the child in the normal way. Again, it doesn't matter if that relationship is defined in the database or not. |
@ajcvickers Thanks - better messaging would be greatly appreciated.
I get that, but by switching to regular entities it means taking on additional behaviours that we don't really want (primarily entity tracking).
|
@optiks If you don't want the entities to be tracked, then use a no-tracking query. We don't recommend using keyless entity types just so they are not tracked. |
@ajcvickers Okie - I'll let it go :-). The reality is that the view result is not an entity (in fact, for us it represents the unification of three different entities) - so it's more of an ideological complaint than a practical one. Pushing no-tracking to the caller is less-than-ideal, but it works. |
@optiks There is inherently no difference between a CLR typed mapped to a view and a CLR type mapped to a table. Either could be updatable or read-only. Either could have a primary key defined, or not have a primary key defined. And so on. Therefore, we ultimately decided to call them all "entity types", because otherwise people read too much semantics into the naming. For example, "view types" where assumed to be read-only because people usually use read-only views. Likewise, people assumed views could not be mapped to types with keys because views don't usually have keys. |
Error message in current 6.0 branch |
Adding regression test to main branch. Leaving issue in 6.0 since the bug is fixed in 6.0 already. |
Background
Hi team (long time no see!),
We're trying to configure a one-to-many from a Keyless Entity Type -> regular entity, however we're running into a
NullReferenceException
during model creation.According to Keyless Entity Types,
Relationships defines a reference navigation property as,
In this case our Keyless Entity Type is trying to map a collection navigation property, so our assumption is that's the cause.
Expected Result
If is this is an explicit design decision not to support collection navigation properties on Keyless Entity Types, then the messaging should be improved to state what the problem is (with references to the applicable documentation). Errors like this can take quite a while to investigate, and good messaging greatly improves the customer experience. I note that #20292 was closed, which looks to be of a similar concern.
More broadly:
Many thanks, and looking forward to hearing your thoughts :)
Classes
Mapping
Result
Include provider and version information
EF Core version: 3.1.5 [this also repros in 3.1.12]
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET Core 3
Operating system: Windows 10
IDE: Visual Studio 2019 16.5
The text was updated successfully, but these errors were encountered: