-
Notifications
You must be signed in to change notification settings - Fork 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
Document: OwnedEntities requires AsNoTracking when queried separately #2205
Comments
@slipdef What is it that you're trying to do that needs an owned entity tracked without it's owner? In other words, why is it an owned entity if it can exist without its owner? |
I indeed don't need an owned entity being tracked without owner. So I would be totally fine if AsNoTracking() is added by default in such cases. |
@slipdef In that case can you elaborate on, "adding AsNoTracking() in these cases doesn't make sense for me." |
I didn't need to write that code before EF Core 3:
I just did
and all worked fine. Now I need because AsNoTracking() is required when querying owned entity without principal. As you pointed out: why would someone need to query owned entity without owner and expect it to be tracked by EF. It doesn't make sense for me too. |
@slipdef Thanks; we will discuss. |
We discussed in triage and decided to keep this on the backlog to consider not requiring AsNoTracking in this case. @smitpatel Can you write down something that explains the main reason owned types can be more confusing than other non-tracked objects. |
Adding |
Might be worth noting that mapping properties of an Owned Entity Type in a projection will not cause this issue but mapping the Owned Entity Type itself in a projection will, even if properties of the owner are mapped. Examples:
This really makes Owned Entity Types painful to use when mapping to view models or DTOs. |
With model public class Customer
{
public int Id { get; set; }
public Address Address { get; set; }
}
[Owned]
public class Address
{
public int CityId { get; set; }
public City City { get; set; }
}
public class City
{
public int Id { get; set; }
} Query var query = db.Customers.Select(c => new
{
One = c,
Two = c.Address,
Three = c.Address.City
}); Above query is marked as tracking by default. If you project Customer, we have enough data to update Address also.
Overall, making implicit non-tracking forces users to understand what case it would be tracked vs non-tracked with above set of complex rules, alongwith potential of data loss if something is not saved correctly. By making AsNoTracking required explicitly, users would know when they are querying owned entity which cannot be updated. So they can take corrective action based on what usage they want. Further, by putting explicit AsNoTracking it becomes clearer that what happens to unrelated entities like City in such queries. |
I have a domain layer that is provided with an Plus: The domain layer has no idea what Entity Framework is. It is persistence agnostic, so there is no Sadly, this is a recurrent pattern with Entity Framework Core: you spent too much energy on the "Demoware" use cases, but leave behind the serious architectual concepts like domain driven design. Don't get me wrong, I really love EF Core, but the time I spent to make thing such as an aggregate working is really high and I start thinking that an implementation at lower level like Dapper would be easier in the end, and using EF Core only as query implementation as the Q in CQRS |
One of our customers reported this error, though the scenario is slightly different. JsonApiDotNetCore dynamically produces LINQ queries of the following form when the API request contains sparse fieldsets (basically selecting a subset of the entity properties and navigations). var customers = db.Customers.Select(c => new Customer()
{
Id = c.Id,
Address = c.Address
}); When no owned entities are involved, this works without explicitly setting a tracking behavior. The entities won't get tracked (obviously), which is fine because we only do this on read-only requests. But when owned entities are used, we now need to explicitly mark the query as non-tracking. I understand that the rules when tracking occurs are complex, but the current experience is pretty inconsistent: We've all been building queries for years that weren't trackable, and we never cared. Now we suddenly need to rationalize and specify when we want to track or not, which is a pain because it may heavily affect performance. It would make more sense to me to downgrade this exception to a warning, which we can suppress in configuration. As a workaround, we're now setting the tracking behavior to Aside from that, in our example query there is actually an owner, so the error message does not seem to apply. Is this a bug? |
@bkoelman We will discuss. |
Note from triage: we discussed this again, but we still believe that the error is useful for preventing people falling into a pit of failure with tracking queries. We are not going to make changes here. |
Make property instances non-owned.
I don't get this. We cannot track primitives or anonymous types either but we don't explode if we happen to project to something else untrackable; why should these explode? I would think the Owned Entity should just be seen as a named set of fields and if I project to it then I am effectively projecting to those fields (which I could do manually already right? but I would throw away the functionality in my type for no reason). I don't get the reason for the error; I already know my type is not a full entity and that I would lose tracking by narrowing to it; but there are lots of queries where that is true and they don't explode... |
The code below just crashes with "A tracking query projects owned entity without corresponding owner in result. Owned entities cannot be tracked without their owner":
It worked fine on EF Core 2. No single word about that in the breaking changes doc!
I have had a hard time finding this comment:
dotnet/efcore#17617 (comment)
I believe this pattern of querying data is quite often. At least I used to it since EF 6. Adding AsNoTracking() in these cases doesn't make sense for me considering the pattern. I understand it's too late to re-consider but please describe that behavior in the breaking changes at least.
The text was updated successfully, but these errors were encountered: