/// <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 JObject CreateDocument([NotNull] IUpdateEntry entry, int?ordinal) { var document = new JObject(); foreach (var property in entry.EntityType.GetProperties()) { var storeName = property.GetJsonPropertyName(); if (storeName.Length != 0) { document[storeName] = ConvertPropertyValue(property, entry.GetCurrentValue(property)); } else if (entry.HasTemporaryValue(property)) { if (ordinal != null && property.IsOrdinalKeyProperty()) { entry.SetStoreGeneratedValue(property, ordinal.Value); } } } foreach (var embeddedNavigation in entry.EntityType.GetNavigations()) { var fk = embeddedNavigation.ForeignKey; if (!fk.IsOwnership || embeddedNavigation.IsOnDependent || fk.DeclaringEntityType.IsDocumentRoot()) { continue; } var embeddedValue = entry.GetCurrentValue(embeddedNavigation); var embeddedPropertyName = fk.DeclaringEntityType.GetContainingPropertyName(); if (embeddedValue == null) { document[embeddedPropertyName] = null; } else if (fk.IsUnique) { var dependentEntry = ((InternalEntityEntry)entry).StateManager.TryGetEntry(embeddedValue, fk.DeclaringEntityType); document[embeddedPropertyName] = _database.GetDocumentSource(dependentEntry.EntityType).CreateDocument(dependentEntry); } else { var embeddedOrdinal = 0; var array = new JArray(); foreach (var dependent in (IEnumerable)embeddedValue) { var dependentEntry = ((InternalEntityEntry)entry).StateManager.TryGetEntry(dependent, fk.DeclaringEntityType); array.Add(_database.GetDocumentSource(dependentEntry.EntityType).CreateDocument(dependentEntry, embeddedOrdinal)); embeddedOrdinal++; } document[embeddedPropertyName] = array; } } return(document); }
public bool TryPropagate(IProperty property, IUpdateEntry entry) { if (_write && (entry.EntityState == EntityState.Unchanged || (entry.EntityState == EntityState.Modified && !entry.IsModified(property)) || (entry.EntityState == EntityState.Added && Equals(_originalValue, entry.GetCurrentValue(property))))) { entry.SetStoreGeneratedValue(property, _currentValue); return(false); } return(_write); }
/// <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 JObject UpdateDocument([NotNull] JObject document, [NotNull] IUpdateEntry entry, int?ordinal) { var anyPropertyUpdated = false; #pragma warning disable EF1001 // Internal EF Core API usage. // #16707 var stateManager = ((InternalEntityEntry)entry).StateManager; #pragma warning restore EF1001 // Internal EF Core API usage. foreach (var property in entry.EntityType.GetProperties()) { if (entry.EntityState == EntityState.Added || entry.IsModified(property)) { var storeName = property.GetJsonPropertyName(); if (storeName.Length != 0) { document[storeName] = ConvertPropertyValue(property, entry.GetCurrentValue(property)); anyPropertyUpdated = true; } } if (ordinal != null && entry.HasTemporaryValue(property) && property.IsOrdinalKeyProperty()) { entry.SetStoreGeneratedValue(property, ordinal.Value); } } foreach (var ownedNavigation in entry.EntityType.GetNavigations()) { var fk = ownedNavigation.ForeignKey; if (!fk.IsOwnership || ownedNavigation.IsOnDependent || fk.DeclaringEntityType.IsDocumentRoot()) { continue; } var embeddedDocumentSource = _database.GetDocumentSource(fk.DeclaringEntityType); var embeddedValue = entry.GetCurrentValue(ownedNavigation); var embeddedPropertyName = fk.DeclaringEntityType.GetContainingPropertyName(); if (embeddedValue == null) { if (document[embeddedPropertyName] != null) { document[embeddedPropertyName] = null; anyPropertyUpdated = true; } } else if (fk.IsUnique) { #pragma warning disable EF1001 // Internal EF Core API usage. // #16707 var embeddedEntry = ((InternalEntityEntry)entry).StateManager.TryGetEntry(embeddedValue, fk.DeclaringEntityType); #pragma warning restore EF1001 // Internal EF Core API usage. if (embeddedEntry == null) { continue; } var embeddedDocument = embeddedDocumentSource.GetCurrentDocument(embeddedEntry); embeddedDocument = embeddedDocument != null ? embeddedDocumentSource.UpdateDocument(embeddedDocument, embeddedEntry) : embeddedDocumentSource.CreateDocument(embeddedEntry); if (embeddedDocument != null) { document[embeddedPropertyName] = embeddedDocument; anyPropertyUpdated = true; } } else { var embeddedOrdinal = 0; var ordinalKeyProperty = GetOrdinalKeyProperty(fk.DeclaringEntityType); if (ordinalKeyProperty != null) { var shouldSetTemporaryKeys = false; foreach (var dependent in (IEnumerable)embeddedValue) { #pragma warning disable EF1001 // Internal EF Core API usage. // #16707 var embeddedEntry = stateManager.TryGetEntry(dependent, fk.DeclaringEntityType); if (embeddedEntry == null) { continue; } if ((int)embeddedEntry.GetCurrentValue(ordinalKeyProperty) != embeddedOrdinal) { shouldSetTemporaryKeys = true; break; } #pragma warning restore EF1001 // Internal EF Core API usage. embeddedOrdinal++; } if (shouldSetTemporaryKeys) { var temporaryOrdinal = -1; foreach (var dependent in (IEnumerable)embeddedValue) { #pragma warning disable EF1001 // Internal EF Core API usage. // #16707 var embeddedEntry = stateManager.TryGetEntry(dependent, fk.DeclaringEntityType); if (embeddedEntry == null) { continue; } embeddedEntry.SetTemporaryValue(ordinalKeyProperty, temporaryOrdinal, setModified: false); #pragma warning restore EF1001 // Internal EF Core API usage. temporaryOrdinal--; } } } embeddedOrdinal = 0; var array = new JArray(); foreach (var dependent in (IEnumerable)embeddedValue) { #pragma warning disable EF1001 // Internal EF Core API usage. // #16707 var embeddedEntry = ((InternalEntityEntry)entry).StateManager.TryGetEntry(dependent, fk.DeclaringEntityType); #pragma warning restore EF1001 // Internal EF Core API usage. if (embeddedEntry == null) { continue; } var embeddedDocument = embeddedDocumentSource.GetCurrentDocument(embeddedEntry); embeddedDocument = embeddedDocument != null ? embeddedDocumentSource.UpdateDocument(embeddedDocument, embeddedEntry, embeddedOrdinal) ?? embeddedDocument : embeddedDocumentSource.CreateDocument(embeddedEntry, embeddedOrdinal); array.Add(embeddedDocument); embeddedOrdinal++; } document[embeddedPropertyName] = array; anyPropertyUpdated = true; } } return(anyPropertyUpdated ? document : null); }