private void OnEntityCreatedHandler(EntityCreatedEventArgs args) { if (!LinqToDBForEFTools.EnableChangeTracker || !Tracking || Context !.ChangeTracker.QueryTrackingBehavior == QueryTrackingBehavior.NoTracking) { return; } var type = args.Entity.GetType(); if (_lastType != type) { _lastType = type; _lastEntityType = Context.Model.FindEntityType(type); } if (_lastEntityType == null) { return; } if (_stateManager == null) { _stateManager = Context.GetService <IStateManager>(); } // It is a real pain to register entity in change tracker // InternalEntityEntry?entry = null; foreach (var key in _lastEntityType.GetKeys()) { //TODO: Find faster way var keyArray = key.Properties.Where(p => p.PropertyInfo != null || p.FieldInfo != null).Select(p => p.PropertyInfo != null ? p.PropertyInfo.GetValue(args.Entity) : p.FieldInfo.GetValue(args.Entity)).ToArray(); if (keyArray.Length == key.Properties.Count) { entry = _stateManager.TryGetEntry(key, keyArray); if (entry != null) { break; } } } if (entry == null) { entry = _stateManager.StartTrackingFromQuery(_lastEntityType, args.Entity, ValueBuffer.Empty); } args.Entity = entry.Entity; }
public EntityEntryGraphNode( InternalEntityEntry entry, TState?state, InternalEntityEntry?sourceEntry, INavigationBase?inboundNavigation) : base(entry, sourceEntry, inboundNavigation) { NodeState = state; }
public EntityEntryGraphNode( InternalEntityEntry entry, InternalEntityEntry?sourceEntry, INavigationBase?inboundNavigation) { _entry = entry; _sourceEntry = sourceEntry; InboundNavigation = inboundNavigation; }
public EntityEntryGraphNode( [NotNull] InternalEntityEntry entry, [CanBeNull] TState?state, [CanBeNull] InternalEntityEntry?sourceEntry, [CanBeNull] INavigationBase?inboundNavigation) : base(entry, sourceEntry, inboundNavigation) { NodeState = state; }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> public virtual bool TryGet( object entity, IEntityType?entityType, [NotNullWhen(true)] out InternalEntityEntry?entry, bool throwOnNonUniqueness) { entry = null; var found = _unchangedReferenceMap?.TryGetValue(entity, out entry) == true || _modifiedReferenceMap?.TryGetValue(entity, out entry) == true || _addedReferenceMap?.TryGetValue(entity, out entry) == true || _deletedReferenceMap?.TryGetValue(entity, out entry) == true || _detachedReferenceMap?.TryGetValue(entity, out entry) == true; if (!found && _hasSubMap && _sharedTypeReferenceMap != null) { if (entityType != null) { if (_sharedTypeReferenceMap.TryGetValue(entityType, out var subMap)) { return(subMap.TryGet(entity, entityType, out entry, throwOnNonUniqueness)); } } else { var type = entity.GetType(); foreach (var keyValue in _sharedTypeReferenceMap) { // ReSharper disable once CheckForReferenceEqualityInstead.2 if (keyValue.Key.ClrType.IsAssignableFrom(type) && keyValue.Value.TryGet(entity, entityType, out var foundEntry, throwOnNonUniqueness)) { if (found) { if (!throwOnNonUniqueness) { entry = null; return(false); } throw new InvalidOperationException( CoreStrings.AmbiguousDependentEntity( entity.GetType().ShortDisplayName(), "." + nameof(EntityEntry.Reference) + "()." + nameof(ReferenceEntry.TargetEntry))); } entry = foundEntry; found = true; } } } } return(found); }
private static InternalEntityEntry?TryPropagateValue(InternalEntityEntry entry, IProperty property, IProperty?generationProperty) { var entityType = entry.EntityType; var stateManager = entry.StateManager; foreach (var foreignKey in entityType.GetForeignKeys()) { for (var propertyIndex = 0; propertyIndex < foreignKey.Properties.Count; propertyIndex++) { if (property == foreignKey.Properties[propertyIndex]) { var principal = foreignKey.DependentToPrincipal == null ? null : entry[foreignKey.DependentToPrincipal]; InternalEntityEntry?principalEntry = null; if (principal != null) { principalEntry = stateManager.GetOrCreateEntry(principal, foreignKey.PrincipalEntityType); } else if (foreignKey.PrincipalToDependent != null) { foreach (var(navigationBase, internalEntityEntry) in stateManager.GetRecordedReferrers(entry.Entity, clear: false)) { if (navigationBase == foreignKey.PrincipalToDependent) { principalEntry = internalEntityEntry; break; } } } if (principalEntry != null) { var principalProperty = foreignKey.PrincipalKey.Properties[propertyIndex]; if (principalProperty != property) { var principalValue = principalEntry[principalProperty]; if (generationProperty == null || !principalProperty.ClrType.IsDefaultValue(principalValue)) { entry.PropagateValue(principalEntry, principalProperty, property); return(principalEntry); } } } break; } } } return(null); }
public EntityEntryGraphNode( InternalEntityEntry entry, InternalEntityEntry?sourceEntry, INavigationBase?inboundNavigation) { Check.NotNull(entry, nameof(entry)); _entry = entry; _sourceEntry = sourceEntry; InboundNavigation = inboundNavigation; }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> public virtual InternalEntityEntry?Propagate(InternalEntityEntry entry) { InternalEntityEntry?chosenPrincipal = null; foreach (var property in entry.EntityType.GetForeignKeyProperties()) { if (!entry.HasDefaultValue(property)) { continue; } var principalEntry = _keyPropagator.PropagateValue(entry, property); chosenPrincipal ??= principalEntry; } return(chosenPrincipal); }
public int Compare(InternalEntityEntry?x, InternalEntityEntry?y) { if (ReferenceEquals(x, y)) { return(0); } if (x is null) { return(-1); } if (y is null) { return(1); } var result = StringComparer.InvariantCulture.Compare(x.EntityType.Name, y.EntityType.Name); if (result != 0) { return(result); } var primaryKey = x.EntityType.FindPrimaryKey(); if (primaryKey != null) { var keyProperties = primaryKey.Properties; foreach (var keyProperty in keyProperties) { var comparer = keyProperty.GetCurrentValueComparer(); result = comparer.Compare(x, y); if (result != 0) { return(result); } } } return(0); }