-
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
Using InboundNavigation in TrackGraph #7308
Comments
I thought I found the answer to the first part of my question, which is how to determine if the current node is on the many side of a one-to-many relationship: context.ChangeTracker.TrackGraph(item, e =>
{
var isOneToMany = e.InboundNavigation?.ForeignKey.PrincipalToDependent?.IsCollection();
}); But this returns true for ManyToOne relationships as well, for example, Order to Customer. And I'm still at a loss as to how I could get a reference to the parent on the other side of var stateManager = e.GetInfrastructure().StateManager;
var internalEntry = stateManager.TryGetEntry(e.Entry.Entity);
var parent = stateManager.GetPrincipal(internalEntry, e.InboundNavigation?.ForeignKey)?.Entity; But |
@tonysneed Inbound navigation is the navigation that was followed to discover this entity in the graph. It does not necessarily point to the principal of the entity. For example, consider the following model: public class Blog
{
public int Id { get; set; }
public ICollection<Post> Posts { get; set; }
}
public class Post
{
public int Id { get; set; }
public Blog Blog { get; set; }
} Now let's track this graph: var post = new Post();
var blog = new Blog { Posts = new List<Post> { post } };
post.Blog = blog; If we call TrackGraph passing in the blog object, then there will be two callbacks:
But if we call TrackGraph passing in the post, then we get:
Note that in the first case when we get the callback for post (the dependent), the blog (the principal) has already been visited and is therefore being tracked. However, in the second case, the callback for post happens before the blog has been discovered. This indicates a problem with what you are trying to do--depending on how entities are discovered, the principal for a relationship may not yet be tracked, and so code to check if it is Added will likely not work. If we assume that you have constrained uses of TrackGraph so that the principals are always visited first--for example, a single relationship with TrackGraph always called on the principal, then you could do something like this: context.ChangeTracker.TrackGraph(blog, e =>
{
if (e.InboundNavigation != null)
{
var referenceToPrincipal = e.InboundNavigation.FindInverse();
Debug.Assert(referenceToPrincipal.IsDependentToPrincipal());
var principalEntry = e.Entry.Context.Entry(e.Entry.Reference(referenceToPrincipal.Name).CurrentValue);
// Handle dependent
e.Entry.State = principalEntry.State == EntityState.Added ? EntityState.Added : EntityState.Unchanged;
}
else
{
// Handle principal
e.Entry.State = e.Entry.IsKeySet ? EntityState.Unchanged : EntityState.Added;
}
}); |
@ajcvickers Thanks, this helps a lot. With I am also able to read the reference property of the node with |
@tonysneed Something like this: context.ChangeTracker.TrackGraph(blog, e =>
{
if (e.InboundNavigation != null)
{
Debug.Assert(!e.InboundNavigation.IsDependentToPrincipal());
var dependentEntry = e.Entry;
var foreignKey = e.InboundNavigation.ForeignKey;
var keyValues = foreignKey.Properties
.Select(p => dependentEntry.Property(p.Name).CurrentValue)
.ToArray();
var principalEntry =
dependentEntry.Context.Entry(
dependentEntry.Context.Find(foreignKey.PrincipalEntityType.ClrType, keyValues));
// Handle dependent
dependentEntry.State = principalEntry.State == EntityState.Added
? EntityState.Added
: EntityState.Unchanged;
}
else
{
// Handle principal
e.Entry.State = e.Entry.IsKeySet ? EntityState.Unchanged : EntityState.Added;
}
}); But that only works if the FK is mapped and an the property values are set before calling Add. See #7389. |
@ajcvickers Thanks, this is helpful. However, I will need access to the referencing entity, as proposed in #7389, because the FK and parent entity may not have the key set because it is an auto-generated identity column. |
Using
TrackGraph
, I would like to be able to set the state of an entity to Added if it is a child in a one-to-many relationship and the parent entity state is Added. For example, if an Order is in an Added state, then I would like to be able to set the OrderDetail to Added as well.I notice that
EntityEntryGraphNode
has anInboundNavigation
property. Is it possible to use it to find the relationship type and a pointer to the entity on the other side of the relationship?The text was updated successfully, but these errors were encountered: