public virtual void AttachGraph(InternalEntityEntry rootEntry, EntityState entityState) => _graphIterator.TraverseGraph( new EntityEntryGraphNode(rootEntry, null) { NodeState = entityState }, PaintAction);
public virtual void Generate(InternalEntityEntry entry) { foreach (var property in entry.EntityType.GetProperties()) { var isForeignKey = property.IsForeignKey(entry.EntityType); if ((property.RequiresValueGenerator || isForeignKey) && property.IsSentinelValue(entry[property])) { if (isForeignKey) { _keyPropagator.PropagateValue(entry, property); } else { var valueGenerator = _valueGeneratorSelector.Select(property, entry.EntityType); Debug.Assert(valueGenerator != null); var generatedValue = valueGenerator.NextSkippingSentinel(property); SetGeneratedValue(entry, property, generatedValue, valueGenerator.GeneratesTemporaryValues); } } } }
public virtual void Generate(InternalEntityEntry entry) { foreach (var property in entry.EntityType.GetProperties()) { var isForeignKey = property.IsForeignKey(entry.EntityType); if ((property.RequiresValueGenerator || isForeignKey) && property.ClrType.IsDefaultValue(entry[property])) { if (isForeignKey) { _keyPropagator.PropagateValue(entry, property); } else { var valueGenerator = _valueGeneratorSelector.Select(property, property.IsKey() ? property.DeclaringEntityType : entry.EntityType); Debug.Assert(valueGenerator != null); SetGeneratedValue(entry, property, valueGenerator.Next(), valueGenerator.GeneratesTemporaryValues); } } } }
private void ForeignKeyPropertyChangedAction(InternalEntityEntry entry, IProperty property, object oldValue, object newValue) { foreach (var foreignKey in entry.EntityType.GetForeignKeys().Where(p => p.Properties.Contains(property)).Distinct()) { var navigations = _model.GetNavigations(foreignKey).ToList(); var oldPrincipalEntry = entry.StateManager.GetPrincipal(entry.RelationshipsSnapshot, foreignKey); if (oldPrincipalEntry != null) { Unfixup(navigations, oldPrincipalEntry, entry); } var principalEntry = entry.StateManager.GetPrincipal(entry, foreignKey); if (principalEntry != null) { if (foreignKey.IsUnique) { var oldDependents = entry.StateManager.GetDependents(principalEntry, foreignKey).Where(e => e != entry).ToList(); // TODO: Decide how to handle case where multiple values found (negative case) // Issue #739 if (oldDependents.Count > 0) { StealReference(foreignKey, oldDependents[0]); } } DoFixup(navigations, principalEntry, new[] { entry }); } } }
/// <summary> /// Binds the mixins to the entity through change tracking. /// </summary> /// <param name="entry">The entity entry.</param> /// <param name="entityType">The entity type.</param> /// <param name="entity">The entity instance.</param> private void BindMixins(InternalEntityEntry entry, IEntityType entityType, object entity) { var mixinHost = entity as ISupportMixins; if (mixinHost != null) { var mixinTypes = entityType .Annotations .Where(a => a.Name == "MixinType") .Select(a => (Type)a.Value) .Distinct() .ToArray(); foreach (var mixinType in mixinTypes) { // Create the mixin. var mixin = (Mixin)Activator.CreateInstance(mixinType); // Set the resolver. mixin.SetPropertyEntryResolver(p => new PropertyEntry(entry, p)); // Assign to the host entity. mixinHost.AddMixin(mixin); } } }
/// <summary> /// Initializes a new instance of the <see cref="PropertyEntry" /> class. Instances of this class /// are returned from methods when using the <see cref="ChangeTracker" /> API and it is not designed /// to be directly constructed in your application code. /// </summary> /// <param name="internalEntry"> The internal entry tracking information about the entity the property belongs to. </param> /// <param name="name"> The name of the property. </param> public PropertyEntry([NotNull] InternalEntityEntry internalEntry, [NotNull] string name) { Check.NotNull(internalEntry, nameof(internalEntry)); Check.NotEmpty(name, nameof(name)); _internalEntry = internalEntry; Metadata = internalEntry.EntityType.GetProperty(name); }
private static IEnumerable<IPropertyBase> GetProperties(InternalEntityEntry entry) { var entityType = entry.EntityType; return entityType.GetKeys().SelectMany(k => k.Properties) .Concat(entityType.GetForeignKeys().SelectMany(fk => fk.Properties)) .Distinct() .Concat<IPropertyBase>(entityType.GetNavigations()); }
protected override Sidecar CreateSidecar(InternalEntityEntry entry = null) { entry = entry ?? CreateInternalEntry(); var properties = entry.EntityType.GetPrimaryKey().Properties .Concat(entry.EntityType.GetForeignKeys().SelectMany(fk => fk.Properties)) .ToList(); return new StoreGeneratedValuesFactory().Create(entry, properties); }
public virtual InternalEntityEntry SnapshotAndSubscribe(InternalEntityEntry entry, ValueBuffer? values) { var entityType = entry.EntityType; if (entityType.UseEagerSnapshots()) { if (values != null) { entry.OriginalValues = new ValueBufferOriginalValues(entry, values.Value); } else { entry.OriginalValues.TakeSnapshot(); } entry.RelationshipsSnapshot.TakeSnapshot(); } else { foreach (var navigation in entityType.GetNavigations().Where(n => n.IsNonNotifyingCollection(entry))) { entry.RelationshipsSnapshot.TakeSnapshot(navigation); } } var changing = entry.Entity as INotifyPropertyChanging; if (changing != null) { changing.PropertyChanging += (s, e) => { var property = TryGetPropertyBase(entityType, e.PropertyName); if (property != null) { _notifier.PropertyChanging(entry, property); } }; } var changed = entry.Entity as INotifyPropertyChanged; if (changed != null) { changed.PropertyChanged += (s, e) => { var property = TryGetPropertyBase(entityType, e.PropertyName); if (property != null) { _notifier.PropertyChanged(entry, property); } }; } return entry; }
private static void SetGeneratedValue(InternalEntityEntry entry, IProperty property, object generatedValue, bool isTemporary) { if (generatedValue != null) { entry[property] = generatedValue; if (isTemporary) { entry.MarkAsTemporary(property); } } }
/// <summary> /// <para> /// Initializes a new instance of the <see cref="PropertyEntry" /> class. /// </para> /// <para> /// Instances of this class are returned from methods when using the <see cref="ChangeTracker" /> API and it is /// not designed to be directly constructed in your application code. /// </para> /// </summary> /// <param name="internalEntry"> The internal entry tracking information about the entity the property belongs to. </param> /// <param name="name"> The name of the property. </param> public PropertyEntry([NotNull] InternalEntityEntry internalEntry, [NotNull] string name) { Check.NotNull(internalEntry, nameof(internalEntry)); Check.NotEmpty(name, nameof(name)); _internalEntry = internalEntry; var property = internalEntry.EntityType.FindProperty(name); if (property == null) { throw new InvalidOperationException(CoreStrings.PropertyNotFound(name, internalEntry.EntityType.DisplayName())); } Metadata = property; }
private void NavigationReferenceChangedAction(InternalEntityEntry entry, INavigation navigation, object oldValue, object newValue) { var foreignKey = navigation.ForeignKey; var dependentProperties = foreignKey.Properties; var principalProperties = foreignKey.PrincipalKey.Properties; // TODO: What if the other entry is not yet being tracked? // Issue #323 if (navigation.PointsToPrincipal()) { if (newValue != null) { SetForeignKeyValue(foreignKey, entry, entry.StateManager.GetOrCreateEntry(newValue)); } else { SetNullForeignKey(entry, dependentProperties); } } else { Debug.Assert(foreignKey.IsUnique); if (newValue != null) { var dependentEntry = entry.StateManager.GetOrCreateEntry(newValue); // Avoid eagerly setting FKs (which may be PKs) in un-tracked entities so as not to mess up // Attach behavior that is based on key values. if (dependentEntry.EntityState != EntityState.Detached) { SetForeignKeyValue(foreignKey, dependentEntry, entry); } } if (oldValue != null) { ConditionallySetNullForeignKey(entry.StateManager.GetOrCreateEntry(oldValue), dependentProperties, entry, principalProperties); } } if (oldValue != null) { ConditionallyClearInverse(entry, navigation, oldValue); } if (newValue != null) { SetInverse(entry, navigation, newValue); } }
public virtual void PropagateValue(InternalEntityEntry entry, IProperty property) { Debug.Assert(property.IsForeignKey()); if (!TryPropagateValue(entry, property) && property.IsKey()) { var valueGenerator = TryGetValueGenerator(property); if (valueGenerator != null) { entry[property] = valueGenerator.Next(); } } }
private bool TryPropagateValue(InternalEntityEntry entry, IProperty property) { var entityType = property.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]) { object valueToPropagte = null; foreach (var navigation in entityType.GetNavigations() .Concat(foreignKey.PrincipalEntityType.GetNavigations()) .Where(n => n.ForeignKey == foreignKey) .Distinct()) { var principal = TryFindPrincipal(stateManager, navigation, entry.Entity); if (principal != null) { var principalEntry = stateManager.GetOrCreateEntry(principal); var principalProperty = foreignKey.PrincipalKey.Properties[propertyIndex]; var principalValue = principalEntry[principalProperty]; if (!principalProperty.IsSentinelValue(principalValue)) { valueToPropagte = principalValue; break; } } } if (valueToPropagte != null) { entry[property] = valueToPropagte; return true; } } } } return false; }
public virtual void PropertyChanging(InternalEntityEntry entry, IPropertyBase propertyBase) { if (!entry.EntityType.UseEagerSnapshots()) { var property = propertyBase as IProperty; if (property != null && property.GetOriginalValueIndex() >= 0) { entry.OriginalValues.EnsureSnapshot(property); } var navigation = propertyBase as INavigation; if ((navigation != null && !navigation.IsCollection()) || (property != null && (property.IsKey() || property.IsForeignKey(entry.EntityType)))) { // TODO: Consider making snapshot temporary here since it is no longer required after PropertyChanged is called // See issue #730 entry.RelationshipsSnapshot.TakeSnapshot(propertyBase); } } }
public virtual void PropertyChanged(InternalEntityEntry entry, IPropertyBase propertyBase) { var snapshot = entry.TryGetSidecar(Sidecar.WellKnownNames.RelationshipsSnapshot); var property = propertyBase as IProperty; if (property != null) { entry.SetPropertyModified(property); if (snapshot != null) { DetectKeyChange(entry, property, snapshot); } } else { var navigation = propertyBase as INavigation; if (navigation != null && snapshot != null) { DetectNavigationChange(entry, navigation, snapshot); } } }
private void DetectPropertyChanges(InternalEntityEntry entry) { var entityType = entry.EntityType; if (entityType.HasPropertyChangedNotifications()) { return; } var snapshot = entry.TryGetSidecar(Sidecar.WellKnownNames.OriginalValues); if (snapshot == null) { return; } foreach (var property in entityType.GetProperties()) { if (property.GetOriginalValueIndex() >= 0 && !Equals(entry[property], snapshot[property])) { entry.SetPropertyModified(property); } } }
public void PropertyChanging(InternalEntityEntry entry, IPropertyBase property) { }
public void DetectChanges(InternalEntityEntry entry) { }
public void StopTracking(InternalEntityEntry entry) { throw new NotImplementedException(); }
public InternalEntityEntry StartTracking(InternalEntityEntry entry) { throw new NotImplementedException(); }
public override void DetectChanges(InternalEntityEntry entry) { DetectChangesCalled = true; base.DetectChanges(entry); }
public IEnumerable<InternalEntityEntry> GetDependents(InternalEntityEntry principalEntry, IForeignKey foreignKey) { throw new NotImplementedException(); }
public void UpdateDependentMap(InternalEntityEntry entry, IKeyValue oldKeyValue, IForeignKey foreignKey) { throw new NotImplementedException(); }
public void UpdateIdentityMap(InternalEntityEntry entry, IKeyValue oldKeyValue, IKey principalKey) { throw new NotImplementedException(); }
public void UpdateIdentityMap(InternalEntityEntry entry, EntityKey oldKey) { throw new NotImplementedException(); }
protected override Sidecar CreateSidecar(InternalEntityEntry entry = null) { return new OriginalValuesFactory().Create(entry ?? CreateInternalEntry()); }
protected abstract Sidecar CreateSidecar(InternalEntityEntry entry = null);
public virtual IEnumerable<InternalEntityEntry> GetDependents(InternalEntityEntry principalEntry, IForeignKey foreignKey) { var keyValue = principalEntry.GetPrincipalKeyValue(foreignKey); Dictionary<EntityKey, HashSet<InternalEntityEntry>> fkMap; HashSet<InternalEntityEntry> dependents; return keyValue != EntityKey.InvalidEntityKey && _dependentsMap.TryGetValue(foreignKey, out fkMap) && fkMap.TryGetValue(keyValue, out dependents) ? dependents : Enumerable.Empty<InternalEntityEntry>(); }
private EntityKey GetKeyValueChecked(IKey key, InternalEntityEntry entry) { var keyValue = entry.GetPrincipalKeyValue(key); if (keyValue == EntityKey.InvalidEntityKey) { // TODO: Check message text here throw new InvalidOperationException(CoreStrings.InvalidPrimaryKey(entry.EntityType.Name)); } return keyValue; }