/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public virtual void AttachGraph(InternalEntityEntry rootEntry, EntityState entityState) => _graphIterator.TraverseGraph( new EntityEntryGraphNode(rootEntry, null) { NodeState = entityState }, PaintAction);
public virtual void PropertyChanged(InternalEntityEntry entry, IPropertyBase propertyBase, bool setModified) { if (_suspended) { return; } var property = propertyBase as IProperty; if (property != null) { entry.SetPropertyModified(property, setModified); if (property.GetRelationshipIndex() != -1) { DetectKeyChange(entry, property); } } else { var navigation = propertyBase as INavigation; if (navigation != null) { DetectNavigationChange(entry, navigation); } } }
public virtual void Generate(InternalEntityEntry entry) { foreach (var property in entry.EntityType.GetProperties()) { var isForeignKey = property.IsForeignKey(); 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); } } } }
public override void DetectChanges(InternalEntityEntry entry) { var entityType = entry.EntityType; var properties = entityType.GetProperties(); foreach (var property in properties) { var current = entry[property]; var old = entry.GetOriginalValue(property); var flag = current != null && current.GetType().Name == typeof(JsonObject<>).Name; TypeInfo type = null; PropertyInfo originalProperty = null; if (flag) { type = current.GetType().GetTypeInfo(); originalProperty = type.DeclaredProperties.Single(x => x.Name == "_originalValue"); old = (string)originalProperty.GetValue(current); var prop = type.DeclaredProperties.Single(x => x.Name == "Json"); current = (string)prop.GetValue(current); } if (property.GetOriginalValueIndex() >= 0 && (!Equals(entry[property], entry.GetOriginalValue(property)) || flag && current != old)) { entry.SetPropertyModified(property); if (flag) { originalProperty.SetValue(entry[property], current); } } } base.DetectChanges(entry); }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public virtual bool SnapshotAndSubscribe(InternalEntityEntry entry) { var entityType = entry.EntityType; if (entityType.UseEagerSnapshots()) { entry.EnsureOriginalValues(); entry.EnsureRelationshipSnapshot(); } var changeTrackingStrategy = entityType.GetChangeTrackingStrategy(); if (changeTrackingStrategy == ChangeTrackingStrategy.Snapshot) { return false; } foreach (var navigation in entityType.GetNavigations().Where(n => n.IsCollection())) { AsINotifyCollectionChanged(entry, navigation, entityType, changeTrackingStrategy).CollectionChanged += entry.HandleINotifyCollectionChanged; } if (changeTrackingStrategy != ChangeTrackingStrategy.ChangedNotifications) { AsINotifyPropertyChanging(entry, entityType, changeTrackingStrategy).PropertyChanging += entry.HandleINotifyPropertyChanging; } AsINotifyPropertyChanged(entry, entityType, changeTrackingStrategy).PropertyChanged += entry.HandleINotifyPropertyChanged; return true; }
/// <summary> /// Initializes a new instance of EntityValidationContext class. /// </summary> /// <param name = "entityEntry"> /// The entity being validated or the entity that owns the property being validated. /// </param> /// <param name = "externalValidationContexts"> /// External contexts needed for validation. /// </param> public EntityValidationContext(InternalEntityEntry entityEntry, ValidationContext externalValidationContext) { //Contract.Requires(entityEntry != null); //Contract.Requires(externalValidationContext != null); _entityEntry = entityEntry; ExternalValidationContext = externalValidationContext; }
// <summary> // Initializes a new instance of EntityValidationContext class. // </summary> // <param name="entityEntry"> The entity being validated or the entity that owns the property being validated. </param> // <param name="externalValidationContext"> External context needed for validation. </param> public EntityValidationContext(InternalEntityEntry entityEntry, ValidationContext externalValidationContext) { DebugCheck.NotNull(entityEntry); DebugCheck.NotNull(externalValidationContext); _entityEntry = entityEntry; ExternalValidationContext = externalValidationContext; }
/// <summary> /// Returns a validator to validate <paramref name="property" />. /// </summary> /// <param name="property"> Navigation property the validator is requested for. </param> /// <returns> Validator to validate <paramref name="property" /> . Possibly null if no validation has been specified for the requested property. </returns> public virtual PropertyValidator GetPropertyValidator( InternalEntityEntry owningEntity, InternalMemberEntry property) { Contract.Requires(owningEntity != null); Contract.Requires(property != null); var entityValidator = GetEntityValidator(owningEntity); return entityValidator != null ? GetValidatorForProperty(entityValidator, property) : null; }
public virtual PropertyValidator GetPropertyValidator( InternalEntityEntry owningEntity, InternalMemberEntry property) { DebugCheck.NotNull(owningEntity); DebugCheck.NotNull(property); var entityValidator = GetEntityValidator(owningEntity); return entityValidator != null ? GetValidatorForProperty(entityValidator, property) : null; }
public virtual void NavigationReferenceChanged(InternalEntityEntry entry, INavigation navigation, object oldValue, object newValue) { if (_navigationListeners == null) { return; } foreach (var listener in _navigationListeners) { listener.NavigationReferenceChanged(entry, navigation, oldValue, newValue); } }
private static void SetGeneratedValue(InternalEntityEntry entry, IProperty property, object generatedValue, bool isTemporary) { if (generatedValue != null) { entry[property] = generatedValue; if (isTemporary) { entry.MarkAsTemporary(property); } } }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public virtual void StateChanging(InternalEntityEntry entry, EntityState newState) { if (_entityStateListeners == null) { return; } foreach (var listener in _entityStateListeners) { listener.StateChanging(entry, newState); } }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public virtual void StateChanged(InternalEntityEntry entry, EntityState oldState, bool skipInitialFixup, bool fromQuery) { if (_entityStateListeners == null) { return; } foreach (var listener in _entityStateListeners) { listener.StateChanged(entry, oldState, skipInitialFixup, fromQuery); } }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> 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(new EntityEntry(entry)); } } }
private bool TryPropagateValue(InternalEntityEntry entry, IProperty property) { 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]) { InternalEntityEntry principalEntry = null; var principal = foreignKey.DependentToPrincipal?.GetGetter().GetClrValue(entry.Entity); if (principal != null) { principalEntry = stateManager.GetOrCreateEntry(principal); } else if (foreignKey.PrincipalToDependent != null) { foreach (var danglerEntry in stateManager.GetRecordedReferers(entry.Entity, clear: false)) { if (danglerEntry.Item1 == foreignKey.PrincipalToDependent) { principalEntry = danglerEntry.Item2; break; } } } if (principalEntry != null) { var principalProperty = foreignKey.PrincipalKey.Properties[propertyIndex]; var principalValue = principalEntry[principalProperty]; if (!principalProperty.ClrType.IsDefaultValue(principalValue)) { entry[property] = principalValue; return true; } } break; } } } return false; }
/// <summary> /// Returns a validator to validate <paramref name="entityEntry" />. /// </summary> /// <param name="entityEntry"> Entity the validator is requested for. </param> /// <returns> /// <see cref="EntityValidator" /> to validate <paramref name="entityEntry" /> . Possibly null if no validation has been specified for the entity. /// </returns> public virtual EntityValidator GetEntityValidator(InternalEntityEntry entityEntry) { DebugCheck.NotNull(entityEntry); var entityType = entityEntry.EntityType; EntityValidator validator = null; if (_entityValidators.TryGetValue(entityType, out validator)) { return validator; } else { validator = _entityValidatorBuilder.BuildEntityValidator(entityEntry); _entityValidators[entityType] = validator; return validator; } }
public virtual void PropertyChanging(InternalEntityEntry entry, IPropertyBase propertyBase) { if (_suspended) { return; } if (!entry.EntityType.UseEagerSnapshots()) { entry.EnsureOriginalValues(); if (propertyBase.GetRelationshipIndex() != -1) { entry.EnsureRelationshipSnapshot(); } } }
/// <summary> /// Returns a validator to validate <paramref name="entityEntry" />. /// </summary> /// <param name="entityEntry"> Entity the validator is requested for. </param> /// <returns> <see cref="EntityValidator" /> to validate <paramref name="entityEntry" /> . Possibly null if no validation has been specified for the entity. </returns> public virtual EntityValidator GetEntityValidator(InternalEntityEntry entityEntry) { Contract.Requires(entityEntry != null); var entityType = entityEntry.EntityType; EntityValidator validator = null; if (_entityValidators.TryGetValue(entityType, out validator)) { return validator; } else { validator = _entityValidatorBuilder.BuildEntityValidator(entityEntry); _entityValidators[entityType] = validator; return validator; } }
private bool TryPropagateValue(InternalEntityEntry entry, IProperty property) { 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]) { 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.ClrType.IsDefaultValue(principalValue)) { valueToPropagte = principalValue; break; } } } if (valueToPropagte != null) { entry[property] = valueToPropagte; return true; } } } } return false; }
private static void DetectPropertyChanges(InternalEntityEntry entry) { var entityType = entry.EntityType; if (entityType.HasPropertyChangedNotifications()) { return; } foreach (var property in entityType.GetProperties()) { if (property.GetOriginalValueIndex() >= 0 && !Equals(entry[property], entry.GetOriginalValue(property))) { entry.SetPropertyModified(property); } } }
public virtual InternalEntityEntry SnapshotAndSubscribe(InternalEntityEntry entry) { var entityType = entry.EntityType; if (entityType.UseEagerSnapshots()) { entry.EnsureOriginalValues(); entry.EnsureRelationshipSnapshot(); } else if (entityType.GetNavigations().Any(n => n.IsNonNotifyingCollection(entry))) { entry.EnsureRelationshipSnapshot(); } 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, setModified: true); } }; } return entry; }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public virtual void PropertyChanging(InternalEntityEntry entry, IPropertyBase propertyBase) { if (_suspended || entry.EntityState == EntityState.Detached) { return; } if (!entry.EntityType.UseEagerSnapshots()) { var asProperty = propertyBase as IProperty; if (asProperty != null && asProperty.GetOriginalValueIndex() != -1) { entry.EnsureOriginalValues(); } if (propertyBase.GetRelationshipIndex() != -1) { entry.EnsureRelationshipSnapshot(); } } }
public void StateChanging(InternalEntityEntry entry, EntityState newState) { Console.WriteLine( " Changing {0} from {1} to {2}.", entry.Entity.GetType().Name, entry.EntityState, newState); if (newState != EntityState.Added && newState != EntityState.Modified) return; var set = services.GetRequiredService<ICultureSet>(); var type = entry.Entity.GetType(); var properties = type.GetProperties().Where(y => y.GetCustomAttribute<LocalizedAttribute>() != null).ToList(); foreach (var y in properties) { try { var origin = entry.GetOriginalValue(entry.EntityType.FindProperty(y.Name)); var current = entry.GetCurrentValue(entry.EntityType.FindProperty(y.Name)); var cultureProvider = services.GetRequiredService<ICultureProvider>(); var culture = cultureProvider.DetermineCulture(); culture = set.SimplifyCulture(culture); Dictionary<string, string> json; if (newState == EntityState.Added) json = new Dictionary<string, string>(); else json = JsonConvert.DeserializeObject<Dictionary<string, string>>(origin.ToString()); if (json.ContainsKey(culture)) json[culture] = current.ToString(); else json.Add(culture, current.ToString()); entry.SetProperty(entry.EntityType.FindProperty(y.Name), JsonConvert.SerializeObject(json)); } catch { break; } } }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public virtual void Unsubscribe(InternalEntityEntry entry) { var entityType = entry.EntityType; var changeTrackingStrategy = entityType.GetChangeTrackingStrategy(); if (changeTrackingStrategy != ChangeTrackingStrategy.Snapshot) { foreach (var navigation in entityType.GetNavigations().Where(n => n.IsCollection())) { AsINotifyCollectionChanged(entry, navigation, entityType, changeTrackingStrategy).CollectionChanged -= entry.HandleINotifyCollectionChanged; } if (changeTrackingStrategy != ChangeTrackingStrategy.ChangedNotifications) { AsINotifyPropertyChanging(entry, entityType, changeTrackingStrategy).PropertyChanging -= entry.HandleINotifyPropertyChanging; } AsINotifyPropertyChanged(entry, entityType, changeTrackingStrategy).PropertyChanged -= entry.HandleINotifyPropertyChanged; } }
public EntityEntry(InternalEntityEntry internalEntry) : base(internalEntry) { }
private void PropertyManipulation( int propertyCount, InternalEntityEntry.PropertyFlag propertyFlag, InternalEntityEntry.PropertyFlag unusedFlag1, InternalEntityEntry.PropertyFlag unusedFlag2) { var data = new InternalEntityEntry.StateData(propertyCount); Assert.False(data.AnyPropertiesFlagged(propertyFlag)); Assert.False(data.AnyPropertiesFlagged(unusedFlag1)); Assert.False(data.AnyPropertiesFlagged(unusedFlag2)); for (var i = 0; i < propertyCount; i++) { data.FlagProperty(i, propertyFlag, true); for (var j = 0; j < propertyCount; j++) { Assert.Equal(j <= i, data.IsPropertyFlagged(j, propertyFlag)); Assert.False(data.IsPropertyFlagged(j, unusedFlag1)); Assert.False(data.IsPropertyFlagged(j, unusedFlag2)); } Assert.True(data.AnyPropertiesFlagged(propertyFlag)); Assert.False(data.AnyPropertiesFlagged(unusedFlag1)); Assert.False(data.AnyPropertiesFlagged(unusedFlag2)); } for (var i = 0; i < propertyCount; i++) { data.FlagProperty(i, propertyFlag, false); for (var j = 0; j < propertyCount; j++) { Assert.Equal(j > i, data.IsPropertyFlagged(j, propertyFlag)); Assert.False(data.IsPropertyFlagged(j, unusedFlag1)); Assert.False(data.IsPropertyFlagged(j, unusedFlag2)); } Assert.Equal(i < propertyCount - 1, data.AnyPropertiesFlagged(propertyFlag)); Assert.False(data.AnyPropertiesFlagged(unusedFlag1)); Assert.False(data.AnyPropertiesFlagged(unusedFlag2)); } for (var i = 0; i < propertyCount; i++) { Assert.False(data.IsPropertyFlagged(i, propertyFlag)); Assert.False(data.IsPropertyFlagged(i, unusedFlag1)); Assert.False(data.IsPropertyFlagged(i, unusedFlag2)); } data.FlagAllProperties(propertyCount, propertyFlag, flagged: true); Assert.Equal(propertyCount > 0, data.AnyPropertiesFlagged(propertyFlag)); Assert.False(data.AnyPropertiesFlagged(unusedFlag1)); Assert.False(data.AnyPropertiesFlagged(unusedFlag2)); for (var i = 0; i < propertyCount; i++) { Assert.True(data.IsPropertyFlagged(i, propertyFlag)); Assert.False(data.IsPropertyFlagged(i, unusedFlag1)); Assert.False(data.IsPropertyFlagged(i, unusedFlag2)); } data.FlagAllProperties(propertyCount, propertyFlag, flagged: false); Assert.False(data.AnyPropertiesFlagged(propertyFlag)); Assert.False(data.AnyPropertiesFlagged(unusedFlag1)); Assert.False(data.AnyPropertiesFlagged(unusedFlag2)); for (var i = 0; i < propertyCount; i++) { Assert.False(data.IsPropertyFlagged(i, propertyFlag)); Assert.False(data.IsPropertyFlagged(i, unusedFlag1)); Assert.False(data.IsPropertyFlagged(i, unusedFlag2)); } }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public virtual void PropertyChanging(InternalEntityEntry entry, IPropertyBase property) { if (_propertyListeners == null) { return; } foreach (var listener in _propertyListeners) { listener.PropertyChanging(entry, property); } }
public void DetectChanges(InternalEntityEntry entry) { }
/// <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> IQueryable ICollectionLoader.Query(InternalEntityEntry entry) => Query(entry);
/// <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 object[] GetDatabaseValues(InternalEntityEntry entry) => GetDatabaseValuesQuery(entry)?.FirstOrDefault();
public override void DetectChanges(InternalEntityEntry entry) { DetectChangesCalled = true; base.DetectChanges(entry); }
public CollectionEntry([NotNull] InternalEntityEntry internalEntry, [NotNull] string name) : base(internalEntry, name) { }
protected NavigationEntry([NotNull] InternalEntityEntry internalEntry, [NotNull] INavigation navigation) : base(internalEntry, navigation) { }
public CollectionEntry([NotNull] InternalEntityEntry internalEntry, [NotNull] INavigation navigation) : base(internalEntry, navigation) { }
/// <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> IQueryable IEntityFinder.Query(INavigation navigation, InternalEntityEntry entry) => Query(navigation, entry);
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public virtual IEnumerable <InternalEntityEntry> GetDependentsUsingRelationshipSnapshot(InternalEntityEntry principalEntry) { return(_map.TryGetValue(_principalKeyValueFactory.CreateFromRelationshipSnapshot(principalEntry), out var dependents) ? dependents : Enumerable.Empty <InternalEntityEntry>()); }
/// <summary> /// Creates a new <see cref = "InternalMemberEntry" /> the runtime type of which will be /// determined by the metadata. /// </summary> /// <param name = "internalEntityEntry">The entity entry to which the member belongs.</param> /// <param name = "parentPropertyEntry">The parent property entry if the new entry is nested, otherwise null.</param> /// <returns>The new entry.</returns> public abstract InternalMemberEntry CreateMemberEntry( InternalEntityEntry internalEntityEntry, InternalPropertyEntry parentPropertyEntry);
public void PropertyChanging(InternalEntityEntry entry, IPropertyBase property) { }
public virtual Sidecar Create(InternalEntityEntry entry) => new OriginalValues(entry);
protected NavigationEntry([NotNull] InternalEntityEntry internalEntry, [NotNull] string name, bool collection) : this(internalEntry, GetNavigation(internalEntry, name, collection)) { }
/// <summary> /// Creates <see cref="EntityValidationContext" /> for <paramref name="entityEntry" />. /// </summary> /// <param name="entityEntry"> Entity entry for which a validation context needs to be created. </param> /// <param name="items"> User defined dictionary containing additional info for custom validation. This parameter is optional and can be null. </param> /// <returns> An instance of <see cref="EntityValidationContext" /> class. </returns> /// <seealso cref="DbContext.ValidateEntity" /> public virtual EntityValidationContext GetEntityValidationContext( InternalEntityEntry entityEntry, IDictionary<object, object> items) { Contract.Requires(entityEntry != null); return new EntityValidationContext(entityEntry, new ValidationContext(entityEntry.Entity, null, items)); }
public void PropertyChanged(InternalEntityEntry entry, IPropertyBase property, bool setModifed) { }
public virtual Sidecar Create(InternalEntityEntry entry) => new RelationshipsSnapshot(entry);
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public virtual IEnumerable <InternalEntityEntry> GetDependents(InternalEntityEntry principalEntry) { return(_map.TryGetValue(_principalKeyValueFactory.CreateFromCurrentValues(principalEntry), out var dependents) ? dependents : Enumerable.Empty <InternalEntityEntry>()); }
private Sidecar CreateSidecar(InternalEntityEntry entry = null) { return(new RelationshipsSnapshotFactory().Create(entry ?? CreateInternalEntry())); }
/// <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 Task <object[]> GetDatabaseValuesAsync( InternalEntityEntry entry, CancellationToken cancellationToken = default) => GetDatabaseValuesQuery(entry)?.FirstOrDefaultAsync(cancellationToken);