-
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
Allow optional dependents to be added later when using table splitting #17422
Comments
As a workaround you could make the child appear as modified: db.ChangeTracker.DetectChanges();
var childEntry = db.Entry(p.Child);
childEntry.State = EntityState.Modified;
db.SaveChanges(); |
Hi @AndriySvyryd , This workaround is rough for normal scenarios because it assumes you are working directly with the change tracker. I want to be able to write my business logic : e.g., retrieve the entity with its null dependent (in my case an owned entity), then set a new object to that property. And on savechanges, I want the context to figure out that the mistakently Added entity needs to be changed to modified. If the shadow property that represents the inferred key is an int then I can test for <0 to know it's truly being Added. Hacky but ok for a short-term workaround. But If we're using Guids and setting them in code that won't really work. Is there something consistent that can be a differentiator after retrieving a null dependent and then replacing it? Since detectchanges thought it was added, the original values are the same as the current values. Hope my question is making sense. thanks! |
@julielerman You can examine the state of the parent. I have not tested this, but it might do the trick: if (entry.State == EntityState.Added)
{
var ownership = entry.Metadata.FindOwnership();
if (ownership != null)
{
var parentKey = ownership.Properties.Select(p => entry.Property(p.Name).CurrentValue).ToArray();
var parent = context.Find(ownership.PrincipalEntityType.ClrType, parentKey);
if (parent != null)
{
var parentEntry = context.Entry(parent);
if (parentEntry.State != EntityState.Added)
{
entry.State = EntityState.Modified;
}
}
}
} And you can make this recursive to handle deeper levels of owned types. |
aha! That's the ticket! If the parent is not new then the owned entity can't be either! Why didn't I thik of that? :( THANKS! |
ps -- looking through commits, it looks like findownership is new to 3. Definitey new to me. :) Is that correct? |
It was in .Internal previously. We made a lot of methods public in 3.0 as we don't want to accidentally break someone relying on them. |
Ok. The workaround is there. But I don't understand how really basic scenario for nullable owned entities doesn't work in the release version and it's not a high priority fix for 3.0. |
@slipdef In short it's because 3.0 is not an LTS release. |
@julielerman we've found (me and @jalbrzym) a workaround for this issue, current implementation of OwnsOne in EF Core does not support standard scenarios, e.g.:
I have described more details here: #19044 (comment) But, we have looked how EF handle value objects in SaveChanges method and we were able to provide a fix for this, you need to override SaveChanges method and put this code there:
There is one disadvantage of this workaround, we were not able to handle OwnsOne inside OwnsOne (yet). EDIT: It's working fine on EF Core 3.1.0-preview3.19554.8 😃 ❤️ |
@AndriySvyryd Do you have a sample of how this can be done when an entity has an alternate key? We have two entities: Parent and Owned (OwnsMany). The parent has a PK which is a Guid and an alternate key that is an int identity. The relation is done on the alternate int key. Your proposed solution for getting the parent of the Owned type works in most cases, but the call to
I understand why the error occurs, but I'm not familiar enough with the inner workings of EFCore to figure out a different way to get the parent of the owned type without using the Find method like this code does. |
@robbaman You can update to 3.1 and avoid any workaround. |
Yes, except that I'm using this technique to change the parent to Modified whenever an Owned type is Modified/Deleted/Added and the parent is Unmodified to trigger the timestamp for the parent to be updated. If there's another way to do that, that'd be cool too. |
@robbaman I see, you are hitting #18529. To make the workaround work with AKs #7391 would be needed. An alternative workaround would be to make sure the affected owned entities have a navigation to the parent (it can be private) and implement an interface, like: public interface IOwnedEntity
{
object GetRoot();
} |
small fix for the example if somebody is using it: |
Reported on https://stackoverflow.com/questions/57628778/efcore-3-and-owned-type-in-same-table-how-do-you-set-owned-instance#_=_
The text was updated successfully, but these errors were encountered: